检查实体框架中是否存在实体的通用方法

本文关键字:实体 方法 是否 框架 检查 存在 | 更新日期: 2023-09-27 17:56:28

类似于检查实体框架中是否存在对象的最佳方法?

我正在寻找一种通用方法来检查DbSet中的实体。像这样的东西,不起作用:

private DbContext DbContext { get; set; }
private DbSet<T> DbSet { get; set; }
public Boolean Exists(T entity) {
    return ((from item in this.DbSet
             where item == entity
             select item).Count() > 0);
}

该行where item == entity适用于 LINQ to SQL,但显然不适用于 LINQ to Entities。由于实体可能具有不同的键,因此我不能让它们都继承自具有已知键的公共摘要进行比较。

我可以这样做,但我担心捕获异常作为验证过程的性能 这也不起作用,因为只要实体被分离,就无法获得OriginalValues属性:

public Boolean Exists(T entity) {
    try {
        var current = this.DbContext.Entry(entity).OriginalValues;
        // Won't reach this line if the entity isn't in the database yet
        return true;
    }
    catch (Exception ex) {
        return false;
    }
}

检查实体框架中是否存在实体的通用方法

您想要检查实体是否通过上下文加载的通用方法还是查询数据库是否存在的通用方法?

对于前一种情况,请使用:

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

对于后一种情况,使用(它也将检查加载的实体):

public bool Exists<T>(params object[] keys)
{
    return this.Set<T>().Find(keys) != null;
}

编辑:

EF 代码首先不应访问此类信息,但可以获取实体键的名称。我认为这样的事情应该有效:

var objContext = ((IObjectContextAdapter)dbContext).ObjectContext;
var objSet = objContext.CreateObjectSet<T>();
var keyNames = objSet.EntitySet.ElementType.KeyMembers.Select(m => m.Name);

但这一切都没有意义。您需要通用方法,但您的实体不共享允许通用方法的必要信息。现在你说你甚至不知道键值。使用这种"通用"方法将需要反射和手动构建表达式树。

感谢@Ladislav让我朝着正确的方向前进。下面是泛型Exists()方法的代码。

我想指出的是,这不需要反思,而且似乎表现得很好。我唯一不感到兴奋的是TryGetObjectByKey()有附加找到的实体的副作用。由于我不希望Exists()出现这种无意的结果,因此如果找到实体,我必须将其分离。

public Boolean Exists(T entity) {
    var objContext = ((IObjectContextAdapter)this.DbContext).ObjectContext;
    var objSet = objContext.CreateObjectSet<T>();
    var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entity);
    Object foundEntity;
    var exists = objContext.TryGetObjectByKey(entityKey, out foundEntity);
    // TryGetObjectByKey attaches a found entity
    // Detach it here to prevent side-effects
    if (exists) {
        objContext.Detach(foundEntity);
    }
    return (exists);
}