Technically you can create entity framework models at run-time, at least by creating an assembly on the fly and using apis and attributes that code first works or by creating required xml for model. But you don't need to create model classes at run-time.
In fact creating model classes at run-time is useless, because you create models to work typed both at compile-time and run-time. You create models at because you want to pass a Type1
to a method or write such typed query like .Where(x=>x.SomeFiled == SomeValue)
.
If you have different instances of application for different customers
If you have different instance of application for different clients, you don't need to do anything specific. Your application has been written ready to use and just use different connection strings in webconfig
and appconfig
for different customers.
If you have a single instance of application for all customers
In such case, which you have a multi-tenant application, you can simply add an overload to your db context constructor that accepts connection string as input. Then when you need to create an instance of your db context, you can use that overload and inject suitable username, password and database name in the connection string based on your tenant detection strategy.
public partial class SampleDbEntities
{
public SampleDbEntities(string connectionString) : base(connectionString)
{
}
}
It's better to put the new overload in a partial class. Then it will not be touched each time when you update the edmx
and .tt
template of context run.
For example you can create connection string and context this way:
var connectionTemplate =
@"metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;" +
@"provider=System.Data.SqlClient;" +
@"provider connection string=""data source={0};" +
@"initial catalog={1};" +
@"persist security info=True;" +
@"user id={2};" +
@"password={3};" +
@"MultipleActiveResultSets=True;App=EntityFramework""";
string connection = string.Format(connectionTemplate,
@"(localdb)\v11.0", @"SampleDB1", @"user1" , @"password1");
var db = new SampleDbEntities(connection);
Or maybe you want windows authentication, then instead of user id and password, use @"integrated security=True;" +
.
You can detect different tenants based on different strategies, including:
- Url of application (domain and sub domain)
- Query string or Route values
- Username
You can give the role of creating suitable context to a class which works based on your tenant strategy.
What should I do if a table in database changed?
Just update your edmx model at design-time and rebuild your application and redistribute it. As mentioned above, if a filed added to a table or a new table added to database and you want to write such typed query in application db.Tabe1.Where(x=>x.Field1==value1)
, then you need to update model from database and rebuilding your application. Regenerating model at run-time doesn't make sense.
How can I increase productivity?
I know your goal is increasing productivity, but generating models at run-time is not what you are looking for. Instead you can create some generic Data Access Layers and generic Business Logic Layers to increase productivity. For example, if you have lot's of entities which need CRUD operations, you can create a EntityBusiness<TContext, TModel>
class and have generic void Create(TModel entity)
, IList<TModel> GetAll(object key)
, TModel GetByKey(object key)
, TModel Update(TModel entity)
, void DeleteByKey(object key)
, etc. This way you can simply create an instance of EntityBusiness<SampleDbEntities, Product>
or inherit from it. The class contains all behavior for a simple CRUD operation and you can enhance it by adding support for some other useful cases like validations. As an example of creating a generic repository and unit of work, take a look at this article in asp.net mvc site.