How to map an Entity framework model to a table name dynamically
Using a code-first approach I'd like to map a single model to multiple table names dynamically. Currently I can do something like modelBuilder.Entity(Of Person)().MapSingleType().ToTable("Managers")
but as the OnModelCreating
method is only called once I can't map it to other table names on the fly.
In our current LinqToSql version we're overriding the MetaModel.GetTable() and returning a new TableAttribute with our dynamic name. I haven't found an attribute like that in EF (even if there were I wouldn't know how to override that yet). So my question is: Is it possible to do this (yet)?
Update
I've found that I can prevent the OnModelCreating
method from caching the mappings by calling
modelBuilder.CacheForContextType = false;
As a result I can assign table definitions on instantiation of the object. This isn't quite how I wanted to do it but it works.
Update
Oh boy, was the above a big mistake...Caching exists for a reason! :) So I'm back to square one with POCO object mapping. I'll post an update if I figure out a solution.
Final
Incase anybody cares how I've currently solved this issue, here you go:
First I created a separate library with the POCO tables and an Interface
public interface IDataContext {
System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }
int SaveChanges();
}
public class TableGeneric {
[Key]
public int Column1 { get; set; }
public string Column2 { get; set; }
public DateTime Column3 { get; set; }
public string Column4 { get; set; }
public string Column5 { get; set; }
}
Then, using the CSharpCodeProvider I created a class that takes the following template and turns it into a type definition:
class DataContext : System.Data.Entity.DbContext, IDataContext {
public System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }
protec开发者_运维百科ted override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder
.Entity<ContextTesting.Interfaces.EF.TableGeneric()
.MapSingleType()
.ToTable("$TableName$");
}
}
With the generated type I'm able to create an instance so here we go
Type typeAccountants = BuildContext.CreateGenericTable("Accountants");
IDataContext context = (IDataContext)Activator.CreateInstance(typeAccountants);
Then the rest is just as if you had a normal DataContext. Hope this helps someone else.
Incase anybody cares how I've currently solved this issue, here you go:
First I created a separate library with the POCO tables and an Interface
public interface IDataContext {
System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }
int SaveChanges();
}
public class TableGeneric {
[Key]
public int Column1 { get; set; }
public string Column2 { get; set; }
public DateTime Column3 { get; set; }
public string Column4 { get; set; }
public string Column5 { get; set; }
}
Then, using the CSharpCodeProvider I created a class that takes the following template and turns it into a type definition:
class DataContext : System.Data.Entity.DbContext, IDataContext {
public System.Data.Entity.DbSet<TableGeneric> TableGeneric { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder
.Entity<ContextTesting.Interfaces.EF.TableGeneric()
.MapSingleType()
.ToTable("$TableName$");
}
}
With the generated type I'm able to create an instance so here we go
Type typeAccountants = BuildContext.CreateGenericTable("Accountants");
IDataContext context = (IDataContext)Activator.CreateInstance(typeAccountants);
Then the rest is just as if you had a normal DataContext. Hope this helps someone else.
精彩评论