Idea to make Massive even less...er...Massive #79

Closed
anderly opened this Issue Aug 29, 2011 · 1 comment

Comments

Projects
None yet
2 participants
@anderly

anderly commented Aug 29, 2011

Hi Rob,

I've been playing with including some sort of dynamic Database/Repository class such as below:

This eliminates having to create new Model classes that derive from DynamicModel for each table in your database.
Instead, you simply call:

Database.Default.Products.Find(Id:1).

Using Database.Default makes some assumptions:

  1. Uses first connection string in web.config by default
  2. Assumes table is named the same as the property you access
  3. Assumes the primary key field is named id

Great convention over configuration approach.

You could also call:

Database.Open("MyConnectionString").Products.Find(Id:1)

OR

Database.Default.Products("tblProducts","ProductID").Find(ProductID:1)

I don't really like this last one above because it could get messy dragging that around everywhere, but maybe a simple fluent interface for one-time registration/mapping would work. Maybe something like:

Database.Default.Products.Map("tblProducts", "ProductID")

From then on any call to Database.Default.Products would create a new DynamicModel using "tblProducts" as the table name and "ProductID" as the primary key field.

Maybe even something similar to register your default connection string too. Something like:

Database.SetDefault("ConnectionStringName")

Curious to get your thoughts?

Here's the class I'm using and it works quite nicely. For DI/IoC, simply add an interface that defines the Default property and Open method.

public class Database : DynamicObject
{
    private string _connectionStringName = ConfigurationManager.ConnectionStrings[0].Name;

    private Database()
    {
    }

    public static dynamic Default
    {
        get { return new Database(); }
    }

    public static dynamic Open(string connectionStringName)
    {
        _connectionStringName = connectionStringName;
        return new Database();
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        var model = new DynamicModel(_connectionStringName, binder.Name, "Id");
        result = model;
        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        var tableName = string.Empty;
        var primaryKeyField = string.Empty;

        var argCount = args.Length;

        if (binder.CallInfo.ArgumentNames.Count > 0)
        {
            var arguments = binder.CallInfo.ArgumentNames.Select((item, index) => new { Name = item, Index = index });
            tableName = args[arguments.Where(n => n.Name == "tableName").FirstOrDefault().Index].ToString();
            primaryKeyField = args[arguments.Where(n => n.Name == "primaryKeyField").FirstOrDefault().Index].ToString();
        }
        else
        {
            if (argCount > 0)
            {
                tableName = args[0].ToString();
            }
            if (argCount > 1)
            {
                primaryKeyField = args[1].ToString();
            }
        }
        var model = new DynamicModel(_connectionStringName, tableName, primaryKeyField);
        result = model;
        return true;
    }
}
@robconery

This comment has been minimized.

Show comment Hide comment
@robconery

robconery Sep 19, 2011

Contributor

Database.Open() does this already yes? Also - the idea of having a class is that it provides you a TableName, PrimaryKey and so on - this is handy if you don't want to write SQL. Appreciate the suggestion but I think I'll keep it the way it is - another reason is that I'm adding in validators and callbacks :)

Contributor

robconery commented Sep 19, 2011

Database.Open() does this already yes? Also - the idea of having a class is that it provides you a TableName, PrimaryKey and so on - this is handy if you don't want to write SQL. Appreciate the suggestion but I think I'll keep it the way it is - another reason is that I'm adding in validators and callbacks :)

@robconery robconery closed this Sep 19, 2011

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment