【问题标题】:EntityFramework Code First - Check if Entity is attachedEntityFramework Code First - 检查是否附加了实体
【发布时间】:2012-04-19 03:03:42
【问题描述】:

我正在尝试在 EntityFramework 4.3 Code First 中更新具有 FK 关系的实体。 我尝试通过调用来附加到相关实体: Entry(item).State = EntityState.Unchanged

我得到以下异常:ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象。

我没有更新这些项目,我的主实体上也没有它们的 id 属性。 是否可以知道哪些实体已附加或未附加?

提前致谢, 拉度

【问题讨论】:

标签: entity-framework-4.3


【解决方案1】:

你可以找到答案here

public bool Exists<T>(T entity) where T : class
{
    return this.Set<T>().Local.Any(e => e == entity);
}

将该代码放入您的上下文中,或者您可以将其转换为类似这样的扩展。

public static bool Exists<TContext, TEntity>(this TContext context, TEntity entity)
    where TContext : DbContext
    where TEntity : class
{
    return context.Set<TEntity>().Local.Any(e => e == entity);
}

【讨论】:

  • 谢谢。这也帮助了我。上面功能的另一个注意事项。你需要把 where T : class,否则编译器会报错。
  • @Sylpheed 谢谢,我已根据您的建议更新了答案。
  • TContext 似乎没有必要。让第一个参数为 DbContext 类型 - public static bool Exists(this DbContext context, TEntity entity)...
  • @Palpie 我提供的答案是针对 EF 4.5,因此当时不存在 DbContext。不过建议很好。
  • “where TContext : DbContext, TEntity: class”在我的系统上不起作用,必须替换为“where TContext : DbContext where TEntity: class”。 AKA,用“where”替换逗号
【解决方案2】:

你可以使用这个方法:

    /// <summary>
    /// Determines whether the specified entity key is attached is attached.
    /// </summary>
    /// <param name="context">The context.</param>
    /// <param name="key">The key.</param>
    /// <returns>
    ///   <c>true</c> if the specified context is attached; otherwise, <c>false</c>.
    /// </returns>
    internal static bool IsAttached(this ObjectContext context, EntityKey key)
    {
        if (key == null)
        {
            throw new ArgumentNullException("key");
        }

        ObjectStateEntry entry;
        if (context.ObjectStateManager.TryGetObjectStateEntry(key, out entry))
        {
            return (entry.State != EntityState.Detached);
        }
        return false;
    }

例如:

     if (!_objectContext.IsAttached(entity.EntityKey))
        {
            _objectContext.Attach(entity);
        }

【讨论】:

  • 我做了一些性能测试并且(令人惊讶地)发现 ObjectStateManager.TryGetObjectStateEntry 比 Set().Local.Any( 慢 70 倍以上
【解决方案3】:

如果您是从 EF Core 延迟加载场景到达这里的,在该场景中,导航属性通过 DbSet.Include() 子句填充到数据层中,而实体附加到 DbContext,然后该实体是分离并传递给业务层,考虑将这样的内容添加到您的 DbContext.OnConfiguring(DbContextOptionsBuilder optionsBuilder) 方法中: optionsBuilder.ConfigureWarnings(warn =&gt; warn.Ignore(CoreEventId.LazyLoadOnDisposedContextWarning)); 错误将被忽略并返回最初的 Include()d 值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    相关资源
    最近更新 更多