我正在使用实体框架,我遇到了"重新找到"我刚刚创建的对象的问题...基本上它是这样的:
string theId = "someId";
private void Test()
{
using(MyEntities entities = new MyEntities())
{
EntityObject o = new EntityObject();
o.Id = theId;
entities.AddToEntityObject(o);
CallSomeOtherMethod(entities);
}
}
void CallSomeOtherMethod(MyEntities ents)
{
EntityObject search = ents.EntityObject.FirstOrDefault(o => o.Id == theId);
if(search == null)
{
Console.WriteLine("wha happened???");
}
}
Run Code Online (Sandbox Code Playgroud)
(不保证代码可以正常运行 - 这一切都来自我的脑海)
为什么查询"找不到"刚刚创建的EntityObject?
如果我在AddToEntityObject之后调用SaveChanges()它可以工作(这并不让我感到惊讶),但为什么它不能正确地从缓存中拉出来?
我对这些东西仍然很绿,所以我希望有一些非常简单的东西,我只是忽略了......
谢谢
Dan*_*ner 19
发生这种情况是因为ents.EntityObject.WhatEver始终查询数据源.这是一个设计决定.他们这样做,因为否则他们必须针对数据源执行查询,针对本地缓存,然后合并结果.正如其中一位开发人员在博客中指出的那样(不记得究竟在哪里)他们无法始终如一地处理这个问题.
你可以想象,你需要妥善处理边缘情况.您可以找到您在本地创建的ID,由数据库中的其他人创建.这将迫使您准备好处理(几乎)每个查询的冲突.也许他们可以创建查询本地缓存的方法和查询数据源的方法,但这也不是聪明的.
您可以查看透明延迟加载实体框架.这将取代普通的代码生成器,您将获得在访问时自动填充其相关实体集合和实体引用的实体.这避免了所有
if (!Entity.ReleatedEntities.IsLoaded)
{
Entity.RelatedEntities.Load();
}
Run Code Online (Sandbox Code Playgroud)
代码片段.您可以查询集合,因为它们始终是隐式加载的.但这个解决方案也不完美.有一些问题.例如,如果您创建新实体并访问相关实体的集合,则会出现异常,因为代码无法从数据库中检索相关实体.还有一个与数据绑定有关的问题,可能还有一些我不知道的问题.
好的是你得到了源代码,并且能够自己修复问题,如果我找到一些时间,我将检查第一个问题.但我很确定它不会那么容易修复,因为我预计如果刚刚创建的实体不是预期的行为,有些情况就是没有命中数据库.
Jan*_*son 18
我处于同样的境地.我写了这个扩展方法,至少对我来说解决了问题(我没有问题,即我的上下文中的冲突......)
public static IEnumerable<T> WhereInclAdded<T>(this ObjectSet<T> set, Expression<Func<T, bool>> predicate) where T : class
{
var dbResult = set.Where(predicate);
var offlineResult = set.Context.ObjectStateManager.GetObjectStateEntries(EntityState.Added).Select(entry => entry.Entity).OfType<T>().Where(predicate.Compile());
return offlineResult.Union(dbResult);
}
Run Code Online (Sandbox Code Playgroud)