Emit DbContext.OnModelCreating每个上下文创建

[英]Emit DbContext.OnModelCreating on every context creation


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?

我首先使用实体​​框架代码来处理我的数据库。我有几个不同名称但结构相同的表,这些表动态地出现在数据库中。我如何在运行时将EntityFramework映射到其中一个表并使用数据,就像我在DbContext的实体上工作一样?

What I've done to make it work:

我做了什么让它工作:

For example, my class what describes structure of dynamically created table is SetElement.

例如,我的类描述了动态创建的表的结构是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.

我还有一些方法来获取,udtate和从动态创建的表中删除与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.

所有工作都按照我的意愿工作,但只有当AddSetElements首先运行时,因为在第一个datacontext创建DbContext.OnModelCreating运行并配置所有映射。但是下一个实例创建不会调用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?

所以,我的问题是:如何在每次创建DataContext实例时调用DbContext.OnModelCreating然后我使用DataContext(string setElementsTableId)来创建它?

I know, my question is similar to 'dynamic table mapping in EF' but I found nothing in the results.

我知道,我的问题类似于'EF中的动态表映射',但我在结果中找不到任何内容。

By the way. If you know another way to solve my problem, you are welcome.

顺便说说。如果您知道解决问题的另一种方法,欢迎您。

2 个解决方案

#1


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.

有一个内置功能可以解决您的问题:`IDbModelCacheKey;其实现将在您的配置中注册。关键是为不同的上下文生成不同的密钥。

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

然后执行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

最后,您的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

我希望这会有所帮助

#2


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.

否则,一个人告诉我,我的问题没有意义,因为几个表中的存储数据不会给出任何成就。更好地将索引添加到数据库,分区表或其他内容。换句话说,这是数据库管理系统问题。但如果有人知道答案,我会非常高兴听到有关EF黑客攻击的事情。

智能推荐

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.silva-art.net/blog/2015/05/07/b9b3c29f7c16c7e460b8a067c4afe97.html



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告