Reputation: 240
I use entity framework code first to work with my database. I have several tables with different names but same structure, and this tables dynamically appears in database. How could I map EntityFramework to one of that tables at run-time and use data from just like I work this over entities of DbContext?
What I've done to make it work:
For example, my class what describes structure of dynamically created table is SetElement
.
Here is my context:
public class DataContext : DbContext
{
public DataContext()
: base("RepositoryConnectionString") { }
string setElementsTableId; // the name of table that need to be dynamicly mapped to
// Enforce model recreating
public DataContext(string setElementsTableId)
: this()
{
this.setElementsTableId = setElementsTableId;
}
/* some other entities */
public DbSet<Entities.SetElement> SetElements { get; set; } // dynamicly mapped entity
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
/* come configurations */
if (!string.IsNullOrEmpty(setElementsTableId))
{
modelBuilder.Entity<Entities.SetElement>().Map(x => x.ToTable(setElementsTableId)); // map SetElements property to dynamicly created table
}
}
}
How I use this:
public static void AddSetElements(ICollection<SetElement> setElements, string tableId)
{
using (ctx = new DataContext(tableId)) // configere DataContext to map tableId table for entity SetElements
try
{
var num = ctx.SetElements.Count();
ctx.SetElements.AddRange(setElements);
ctx.SaveChanges();
}
catch (Exception e)
{
}
}
I have also some methods to get, udtate and remove data from dynamicly created tables that are same to AddSetElements
.
All works just as I wish but only if AddSetElements
runs first, because at the first datacontext creating DbContext.OnModelCreating
runs and configure all mappings. But next instance creation doesn't call DbContext.OnModelCreating
.
So, my question is: how to call DbContext.OnModelCreating
everytime of creating an instance of DataContext
then I use DataContext(string setElementsTableId)
to create it?
I know, my question is similar to 'dynamic table mapping in EF' but I found nothing in the results.
By the way. If you know another way to solve my problem, you are welcome.
Upvotes: 4
Views: 2358
Reputation: 15413
There is a built-in feature which may address your issue : `IDbModelCacheKey ; the implementation of which is to be registered in your configuration. The point is to generate a different key for your different contexts.
I would go for something like :
First, the configuration
public class EntityFrameworkConfiguration: DbConfiguration
{
public EntityFrameworkConfiguration()
{
this.SetModelCacheKey(ctx => new EntityModelCacheKey((ctx.GetType().FullName + ctx.Database.Connection.ConnectionString).GetHashCode()));
}
}
Then the implementation of the IDbModelCacheKey
public class EntityModelCacheKey : IDbModelCacheKey
{
private readonly int _hashCode;
public EntityModelCacheKey(int hashCode)
{
_hashCode = hashCode;
}
public override bool Equals(object other)
{
if (other == null) return false;
return other.GetHashCode() == _hashCode;
}
public override int GetHashCode()
{
return _hashCode;
}
}
Finally, your DataContext
public class DataContext : DbContext
{
string setElementsTableId;
// use the setElementsTableId as extended property of the
// connection string to generate a custom key
public DataContext(string setElementsTableId)
: base(ConfigurationManager.ConnectionStrings["RepositoryConnectionString"]
+ "; Extended Properties=\"setElementsTableId=" + setElementsTableId + "\"")
{
this.setElementsTableId = setElementsTableId;
}
public DbSet<Entities.SetElement> SetElements { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (!string.IsNullOrEmpty(setElementsTableId))
{
modelBuilder.Entity<Entities.SetElement>().Map(x => x.ToTable(setElementsTableId));
}
}
}
I hope this will be of some help
Upvotes: 5
Reputation: 240
Look like nobody knows answer...
Otherwise, one man told me that my question is meaningless because of storage data in several tables will not give any achievement. More better to add indexes to database, partitioning table or something else. In other words this is Database Management System problem. But if some one knows answer I'll be very pleasured to hear something about EF hack.
Upvotes: 0