检查entity framework中是否存在实体的通用方法?
类似于检查entity framework中是否存在对象的最佳方法?
我正在寻找一种通用的方式来检查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。 由于实体可能具有不同的密钥,我不能让它们全部从具有已知密钥的通用摘要inheritance来进行比较。
我可以做到这一点,但我担心捕获作为validation过程的exception的性能这不起作用,因为只要实体分离,无法获得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) { 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);
但是这一切都没有意义。 你想要通用的方法,但你的实体不共享必要的信息,以允许通用的方法。 现在你说你甚至不知道关键的价值。 使用这种“通用”的方法将需要反思和手动构buildexpression式树。
感谢@Ladislav让我朝着正确的方向前进。 这是一个通用Exists()
方法的代码。
我想指出,这不需要反思,似乎performance相当好。 我不感到兴奋的唯一的事情是TryGetObjectByKey()
有附加find的实体的副作用。 由于我不想让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); }