简体   繁体   English

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

[英]Generic Way to Check If Entity Exists In Entity Framework?

Similar to Best way to check if object exists in Entity Framework?类似于检查实体框架中是否存在 object 的最佳方法?

I'm looking for a generic way to check for an entity in a DbSet .我正在寻找一种通用方法来检查DbSet中的实体。 Something like this, which doesn't work:像这样的东西,这是行不通的:

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

The line where item == entity works in LINQ to SQL, but apparently not with LINQ to Entities. where item == entity在 LINQ 到 SQL 中工作的行,但显然不是 LINQ 到 Entities。 Since the entities may have different keys I can't have them all inherit from a common abstract with a known key for comparison.由于实体可能有不同的键,我不能让它们全部继承自具有已知键的公共抽象以进行比较。

I could do this, but I'm worried about the performance of catching exceptions as a verification process This doesn't work either since as long as the entity is detached the OriginalValues property can't be obtained: 我可以这样做,但我担心将捕获异常作为验证过程的性能 这也不起作用,因为只要分离了实体,就无法获得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;
    }
}

Do you want generic way to check if entity was loaded by context or generic way to query database if entity exists?如果实体存在,你想要通用的方式来检查实体是否被上下文加载或者通用的方式来查询数据库吗?

For the former case use:对于前一种情况使用:

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

For the latter case use (it will check loaded entities as well):对于后一种情况使用(它也会检查加载的实体):

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

Edit:编辑:

EF code first is not supposed to access this kind of information but it is possible to get name of entity keys. EF 代码首先不应访问此类信息,但可以获取实体键的名称。 I think something like that should work:我认为这样的事情应该有效:

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

But this all doesn't make sense.但这一切都没有意义。 You want generic approach but your entities doesn't share necessary information to allow generic approach.您想要通用方法,但您的实体不共享必要的信息以允许通用方法。 Now you say that you even don't know key values.现在你说你连键值都不知道。 Using this "generic" approach will require reflection and manual building of expression tree.使用这种“通用”方法将需要反思和手动构建表达式树。

Thanks to @Ladislav for getting me in the right direction.感谢@Ladislav 让我朝着正确的方向前进。 Here's the code for a generic Exists() method.下面是通用Exists()方法的代码。

I'd like to note that this doesn't require reflection and seems to perform quite well.我想指出,这不需要反思,而且似乎表现得很好。 The only thing I'm not thrilled about is that TryGetObjectByKey() has the side-effect of attaching the found entity.唯一让我不高兴的是TryGetObjectByKey()具有附加找到的实体的副作用。 Since I don't want Exists() to have that unintentional result I have to detach the entity if it was found.因为我不希望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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM