Emit DbContext.OnModelCreating每个上下文创建

时间:2015-05-07 08:26:27

标签: c# entity-framework entity-framework-6

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

我为使其成功而做了什么:

例如,我的类描述了动态创建的表的结构是SetElement

这是我的背景:

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
        }
    }
}

我如何使用它:

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)
       {
       }
 }

我还有一些方法可以从动态创建的表中获取,更新和删除与AddSetElements相同的数据。

一切正常,但只有AddSetElements首先运行,因为在第一个datacontext创建DbContext.OnModelCreating运行并配置所有映射。但是下一个实例创建不会调用DbContext.OnModelCreating

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

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

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

2 个答案:

答案 0 :(得分:4)

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

我会选择类似的东西:

首先是配置

public class EntityFrameworkConfiguration: DbConfiguration
{
    public EntityFrameworkConfiguration()
    {
        this.SetModelCacheKey(ctx => new EntityModelCacheKey((ctx.GetType().FullName + ctx.Database.Connection.ConnectionString).GetHashCode()));
    }
}

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

最后,你的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)); 
    }
  }
}

我希望这会有所帮助

答案 1 :(得分:0)

看起来没有人知道答案......

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