【问题标题】:Updating records of different type, but with same base class更新不同类型但具有相同基类的记录
【发布时间】:2020-02-20 20:34:19
【问题描述】:

我正在尝试更新不同类型的记录,但所有这些都基于相同的基本类型 BaseEntity(其成员中有 OwnerId)

这样做是为了让我可以将所有表记录的所有权从一个用户转移给另一个用户。

这是我必须要做的事情:

public ActionResult TransferOwnership(int sourceUserId, int targetUserId)
{
    var metadata = ((IObjectContextAdapter)Context).ObjectContext.MetadataWorkspace;
    var tables = metadata.GetItems(DataSpace.SSpace).Where(x => x.BuiltInTypeKind == BuiltInTypeKind.EntityType).ToList();

    foreach (var table in tables)
    {
        var tableName = table.GetType().GetProperty("Name").GetValue(table);
        List<BaseEntity> entities = Context.Database.SqlQuery<BaseEntity>($"SELECT * FROM {tableName} WHERE OwnerId = {sourceUserId}").ToList();

        foreach (var entity in entities)
        {
            entity.OwnerId = targetUserId;
            Context.Entry(entity).State = EntityState.Modified; //this fails
        }

        if (entities.Count > 0)
            Context.SaveChanges();
    }

    return Ok();
}

在我设置实体状态的那一行,我收到一条错误消息,指出上下文未跟踪类型 BaseEntity。

我可以使用表名将对象转换为其真实类型,但是我需要执行以下操作:

Context.MyTable1.Attach(entity);

但这失去了它的一般吸引力;我必须明确地处理所有表。

我记得在旧版本的 EF 中,您可以执行 Context.ChangeTracker.Attach(entity) 之类的操作,但似乎已经不存在了。

有什么想法吗?

【问题讨论】:

    标签: c# .net entity-framework-6 .net-4.0


    【解决方案1】:

    在 EF Core DbContext 中有 Attach 方法,但在 EF DbSet 中有 Attach(Object entity) 方法。您应该使用 DbSet 将更改跟踪机制添加到您的通用实体。

    来源:Microsoft docs

    更新:

    你可以试试这个:context.Set(entity.GetType()).Attach(entity)

    【讨论】:

      【解决方案2】:

      我最终做了:

      public async Task<ActionResult> TransferOwnership(int sourceUserId, int targetUserId)
      {
          var metadata = ((IObjectContextAdapter)Context).ObjectContext.MetadataWorkspace;
          var tables = metadata.GetItems(DataSpace.SSpace).Where(x => x.BuiltInTypeKind == BuiltInTypeKind.EntityType).ToList();
          //some entities were cast to their proxy types which were unconvertable with Convert.ChangeType...
          Context.Configuration.ProxyCreationEnabled = false;
      
          foreach (var table in tables)
          {
              var tableName = table.GetType().GetProperty("Name").GetValue(table);
              var type = Assembly.GetAssembly(typeof(BaseEntity)).GetTypes().SingleOrDefault(x => x.Name == tableName.ToString());
      
              List<object> entities = await Context.Database.SqlQuery(type, $"SELECT * FROM {tableName} WHERE OwnerId = {sourceUserId}").ToListAsync();
      
              foreach (var entity in entities)
              {
                  var e = entity as BaseEntity;
                  e.OwnerId = targetUserId;
                  Context.Set(type).Attach(Convert.ChangeType(e, type));
                  Context.Entry(e).State = EntityState.Modified;
              }
      
              if (entities.Count > 0)
                  Context.SaveDirect();
          }
      
      
          return Ok();
      }
      

      【讨论】:

        猜你喜欢
        • 2013-03-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-27
        • 2019-12-18
        • 2019-08-18
        • 2020-07-21
        • 2021-02-10
        相关资源
        最近更新 更多