我只是用Entity Framework弄湿了自己的脚,但是我对DBSet对象的一些行为感到有些莫名其妙。当我调用Find()方法时,它似乎意识到我最近添加的(但尚未保存的)项目的集合,但是当我尝试查询DBSet时,它似乎只包含一直存在的项目。有没有简单的方法来解决这个问题?我包括一些代码,我已经做了尝试解决这个问题,但是当它开始通过从我的“添加”变更集的项目进行迭代,我得到这个错误:有没有办法在DBSet的查询中包含本地缓存的项目?
"Unable to create a constant value of type EntityType. Only primitive types ('such as Int32, String, and Guid') are supported in this context."
internal DbContext Context { get; set; }
protected DbSet<T> DBSet { get; set; }
public virtual IEnumerable<T> Get(
Expression<Func<T, bool>> filter = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
bool ignoreCachedChanges = false)
{
IQueryable<T> oReturn = DBSet;
// This block is intended to adjust the queryable source to account for changes
if (!ignoreCachedChanges)
{
oReturn = oReturn.Except(Context.ChangeTracker.Entries<T>().Where(x => x.State == System.Data.EntityState.Deleted).Select(x => x.Entity));
oReturn = oReturn.Union(Context.ChangeTracker.Entries<T>().Where(x => x.State == System.Data.EntityState.Added).Select(x => x.Entity));
}
if (filter != null)
oReturn = oReturn.Where(filter);
if (orderBy != null)
return orderBy(oReturn).ToList();
else
return oReturn.ToList();
}
// NOTE: Get By ID uses Find which considers the queued-but-not-yet-applied changes
public virtual T GetByID(object id)
{
return DBSet.Find(id);
}
(在上下文有帮助的情况下,我这样做是因为我想设置一个单元测试,在其中填充我的(本地)上下文,以满足特定测试环境的项目......我很快就不需要应用这些变化,因为他们真的只适用于特定的测试,但我可以,如果需要的话...在这样做,我很惊讶地发现,存储库不包括其查询结果中的变化项目 - 除非我在做FindByID - 所以我也希望我能解决这种明显的不一致性,或者g或者更好的理解为什么这是不可行的或者不是一个好主意? :))
谢谢!这让我更好地理解发生了什么。另外,如果您碰巧读到:这是我的存储库查询方法的明智方法吗?我会倾向于认为,因为这个“离线”集合具有排队的插入/删除,它应该考虑那些(如DBSet.Find()似乎这样做),但是有没有理由不这样做,我可能会忽略? – Steven
@Steven:'Find'非常特别。它只查询主键。这可以在内存(第1步)和SQL中使用(第2步,如果第1步中没有发现任何内容)。对于其他查询,您必须记住,EF必须使用LINQ to Entities执行查询,然后使用LINQ to Objects查询来构建联合。有些查询甚至不能在LINQ to Objects(例如使用'EntityFunctions')时完成。或者相同的查询可以有不同的行为(例如,字符串搜索的区分大小写)。仅使用一个查询规范执行两个查询并非易事,也不可能。 – Slauma
(续)可能是它没有按照您的意愿实施的原因。这些也是您的通用泛型实现在ChangeTracker中构建DB查询对象和对象的联合的原因:您的'filter'应用于LTO或LTE时可能会给出不同的结果,或者它甚至不适用于LTO。我怀疑一个干净的通用实现是可能的。我会尽量避免你需要查询'ChangeTracker'。如果你真的需要,不要尝试一种通用的方法,只能在你的特定情况下进行,并且必须在特定的查询中进行。 – Slauma