Question?

Jul 16, 2009 at 3:49 PM

Hi,

I must say that you're doing great job with this. I like the idea of Fluent ADO.NET as there are still some of us that cannot use any ORM on projects. However I have one question for you.

Why are you using different project (different fluentcommand class)for every type of database? What do you think about more generic solution built around IDbCommand and other related interfaces? Problem regarding concrete instances can be resolved using factories (which could be injected) or using lambda methods.  Or do you maybe provide some additional features for each type of database server, which I'm failing to see?

 

Thanks,

Edin

Coordinator
Jul 16, 2009 at 5:04 PM

Hi Edin,

Great question, and one that I struggled with for a long time.  In the end I decided to go with the simplest, and most configurable solution.

If I wrap everything in an interface you loose the ability to customization each solution, you end up with the least possible denominator.   For example, if I was using SQL Server 2008, I might want to take advantage of the new Geometry, Geography, DateTime2, Date, Time, or Hierarchy column types.  With an interface based approach I would have a much harder time implementing that because those column types do not exist on many other database systems.

Also, I wanted to make things usable with minimal setup, and a very straight forward api.  Change the connection string and it should just work.  So everything else is just overhead.

So basically, I want to be free to customize for unique features of each database and ease of use.

Thank you for the question.

Jul 16, 2009 at 8:26 PM

Yes, I undersand your reasons and I agree with using the simplest solution possible. But still I would appreciate if I would not need to write new code when I want to support another SQL database (Postgre for example). Yes, you are absolutely right with the least possible denominator argument, but I think there is a solution and a rather good one. By using Extension methods you can easly take advantage of specific database engines. My idea is to write a common Fluent API around interfaces mentioned earlier and then write extension methods (also fluent) for each specific database. By doing this it is possible to get best of both worlds.

To get more sense of the idea here some code(only prototyping):

FluentDbCommand<SqlCommand> sqlCommand = new FluentDbCommand<SqlCommand>();
FluentDbCommand<OleDbCommand> oleDbCommand = new FluentDbCommand<OleDbCommand>();

DataTable oleDbTable = oleDbCommand.UseConnection(connection)
                        .UsingQuery("SELECT * FROM USERS WHERE ID=@id")
                        .AddParameter("@id", 1)
                        .AsDatatable();

DataTable sqlTable = sqlCommand.UseConnection(connection)
                                                    .UsingQuery("SELECT * FROM USERS WHERE ID=@id")
                                                    .AddParameter("@id", 1)
                                                    .NotificationAutoEnlist(true)
                                                    .AsDatatable(); 

You can see that I'm using a property (NotificationAutoEnlist) that does not exist in IDbCommand interface. And that's possible because of following extension method.

public static class SQLServerSpecificExtensions
{
        public static FluentDbCommand<SqlCommand> NotificationAutoEnlist(this FluentDbCommand<SqlCommand> command, bool value)
        {
            command.InnerCommand.NotificationAutoEnlist = true;
            return command;
        }
}

Of course you can add your mapper methods to this model as well. 

Anyway I just wanted to share some thoughts. 

Keep up the good work.

 

 

Coordinator
Jul 16, 2009 at 11:43 PM

If you are going to pass in the connection anyway, then you don't nessesarily need to pass in the command...let me work this one out.

The thing is, the connection (which is typed) has a conn.CreateCommand.  The Command has a CreateParameter.  Once you have the command, everything else is typed.

 

So an alternative might look like this:

new FluentDbCommand<MyData>.UseConnection(conn).blah.blah.blah.AsList();
No need to pass in the command type at all.  Just the connection object.
Jul 17, 2009 at 12:06 AM

You are right about connection being typed and not needing to pass command type. But in that case it would not be possible to target specific IDbCommand implementation using extension method.