【问题标题】:How to get proper DbSet<Entity> in DbContext when SavingChanges?SavingChanges 时如何在 DbContext 中获取正确的 DbSet<Entity>?
【发布时间】:2016-05-13 17:41:45
【问题描述】:

我有一个类似的 DbContext

public class MyContext : DbContext
{
   public DbSet<Entity1> Entities1 { get; set; }
   public DbSet<Entity2> Entities2 { get; set; }
   . . .
}

其中Entity1Entity2 继承基类

public abstract class BaseEntity
{
   [DatabaseGenerated(DatabaseGeneratedOption.None)]
   public int Id { get; set; }
   . . .
}

出于某种原因,我需要删除数据库中的自动增量并在上下文中进行自定义自动增量以避免数据库影响。所以我决定估计Id 列中的当前最大值并增加它。
我创建了一个简单的方法

private int GetMaxId(IQueryable<BaseEntity> set)
{
   if (set.Count() == 0) return 0;
   else return set.Max(x => x.Id);
}

所以在上下文构造函数中,我执行以下操作:

public MyContext() : base("MyConnection")
{
   . . .

   var objectContext = ((IObjectContextAdapter)this).ObjectContext;
   objectContext.SavingChanges += (sender, args) =>
   {
      foreach (var entry in ChangeTracker.Entries())
      {
         var entity = entry.Entity;
         var state = entry.State;
         if (entity is BaseEntity)
         {
            switch (entry.State)
            {
               case EntityState.Added:
                  var set = Set<entity.GetType()>();
                  (entity as BaseEntity).Id = GetMaxId(set) + 1;
               . . .
            }
         }
      }
      ChangeTracker.DetectChanges();
   };

   . . .
}

但问题是我不能像 Set&lt;entity.GetType()&gt;()Set&lt;typeof(entity)&gt;() 那样构造 DbSet - 它说最后一个 ) 是无效的表达式。虽然它不依赖于括号的数量\顺序。
Set(entity.GetType()) 也不适合我,因为它返回一个无类型的 DbSet。

请告诉我如何解决这个问题或我做错了什么。

【问题讨论】:

    标签: c# asp.net-mvc entity-framework auto-increment dbcontext


    【解决方案1】:

    您可以使用以下代码按实体类型获取DbSet

    var set = Set(entity.GetType());
    

    【讨论】:

    • 正如我所说,Set(TEntity) 是无类型的,所以它不适合我
    • 是的,对不起。你试过var set = Set(entity.GetType()).Cast&lt;BaseEntity&gt;();吗?
    • 不幸的是它失败了。异常类似于“我们不能基于非泛型对象 DbSet 为 Entity1 类型的对象构造 DbSet”。附言但不错的尝试!我真的希望它有效)
    【解决方案2】:

    您不能在运行时将类型确定为泛型类型参数。 在您的情况下,此解决方法应该有效:

    public MyContext() : base("MyConnection")
    {
      var objectContext = ((IObjectContextAdapter) this).ObjectContext;
      objectContext.SavingChanges += (sender, args) =>
      {
        foreach (var entry in ChangeTracker.Entries())
        {
          var entity = entry.Entity;
          var state = entry.State;
          if (entity is BaseEntity)
          {
            ProcessEntity((BaseEntity)entity, state);
          }
        }
        ChangeTracker.DetectChanges();
      };
    }
    
    private void ProcessEntity<T>(T entity, EntityState state) where T : BaseEntity
    {
      switch (state)
      {
        case EntityState.Added:
          var set = Set<T>();
          (entity as BaseEntity).Id = GetMaxId(set) + 1;
          break;
      }
    }
    

    【讨论】:

    • 据我了解,您的意思是像private void ProcessEntity&lt;T&gt;(T entity, EntityState state) where T : class 这样的声明,否则这是一个错误,因为Set&lt;T&gt; 中的T 必须是引用类型。所以如果你写where T : class 那么set in GetMaxId(set) 不能用作类型参数
    • 没错,应该是where T : class。我看到你对GetMaxId 的问题。您可以在 ProcessEntity where T : BaseEntity 上添加通用约束,而不是 T : class。那么所有的约束应该是相等的。对不起,复杂了,我这里没有VS,所以我无法尝试。
    • 在这种情况下我不能调用ProcessEntity(entity, state) 因为在上下文构造函数entityobject 类型并且没有隐式引用转换
    • 是的,但是由于您正在检查if(entity is BaseEntity),您可以放心地使用它。我终于接触到了VS。我正在用可以编译的最终版本编辑我的答案。
    • 正如我回答@alisabzevari Cast&lt;BaseEntity&gt;() 编译,但在运行时抛出异常
    【解决方案3】:

    DbSet 的演员阵容中长期挣扎后,我终于找到了解决方案。问题是我们不需要转换DbSet,我们必须转换它的元素。

    这很明显。

    因此GetMaxId 的最终版本(在我们检查entityGetMaxId 调用之前是BaseEntity 的情况下)是

        private int GetMaxId(DbSet set)
        {
            int max = 0;
            foreach (var item in set)
            {
                int id = (item as BaseEntity).Id;
                if (id > max) max = id;
            }
            return max;
        }
    

    对应的情况是

    case EntityState.Added:
       (entity as BaseEntity).Id = GetMaxId(Set(entity.GetType())) + 1;
       . . .
    

    就像@alisabzevari 所说的那样。

    【讨论】:

      猜你喜欢
      • 2012-11-11
      • 2021-05-12
      • 1970-01-01
      • 2013-07-16
      • 2017-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-13
      相关资源
      最近更新 更多