Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 实体框架:重新查找最近添加到上下文的对象_Entity Framework - Fatal编程技术网

Entity framework 实体框架:重新查找最近添加到上下文的对象

Entity framework 实体框架:重新查找最近添加到上下文的对象,entity-framework,Entity Framework,我正在使用实体框架,我在“重新查找”刚创建的对象时遇到了问题。。。基本上是这样的: string theId = "someId"; private void Test() { using(MyEntities entities = new MyEntities()) { EntityObject o = new EntityObject(); o.Id = theId; entities.AddToEntityObject(o); CallSomeOt

我正在使用实体框架,我在“重新查找”刚创建的对象时遇到了问题。。。基本上是这样的:

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???");
  }
}
(顺便说一句,不保证代码有效-这都是我的想法)

为什么查询没有“找到”刚刚创建的EntityObject

如果我在AddToEntityObject之后调用SaveChanges(),它会工作(这并不奇怪),但为什么它不能正确地从缓存中提取呢

我对这件事还不了解,所以我希望有一些真正简单的事情我只是忽略了


谢谢

发生这种情况是因为ents.EntityObject.WhatEver总是查询数据源。这是一个设计决策。他们这样做,因为否则他们必须对数据源、本地缓存执行查询,然后合并结果。正如一位开发人员在博客中指出的那样(记不清具体位置),他们无法始终如一地处理这个问题

正如你可以想象的那样,有很多角落和边缘的情况,你必须妥善处理。您可以找到您在本地创建的id,该id是由数据库中的其他人创建的。这将迫使您准备好处理(几乎)每个查询上的冲突。也许他们可以创建查询本地缓存的方法和查询数据源的方法,但这也不明智

你可以看一看。这将替换普通的代码生成器,您可以在access上获得自动填充其相关实体集合和实体引用的实体。这避免了所有的错误

if (!Entity.ReleatedEntities.IsLoaded)
{
   Entity.RelatedEntities.Load();
}
代码片段。您可以查询集合,因为它们总是隐式加载的。但这个解决方案也不完美。有一些问题。例如,如果创建一个新实体并访问相关实体的集合,则会出现异常,因为代码无法从数据库中检索相关实体。还有一个关于数据绑定的问题,可能还有一些我不知道的问题


好的方面是,您获得了源代码,能够自己解决问题,如果我有时间,我将检查第一个问题。但我很确定,修复起来不会那么容易,因为我认为如果实体刚刚创建,那么某些情况就不会影响数据库,这不是预期的行为

您有很多选择。您可以使用另一个分部类扩展
ObjectContext
,以创建自己的机制来检索最近添加的信息


或者您可以在
ObjectContext
上放置一个扩展方法,该方法可以查看
ObjectContext.ObjectStateManager
以查找“添加的”
ObjectStateEntries
,然后使用LINQ to对象来查找您要查找的内容。

我最近也遇到了同样的问题。在这个问题被问到两年后,我发布了这个答案,希望这段代码可以帮助搜索答案的人

我基本上实现了一个名为“Find”的扩展方法(正如Alex James所建议的),它的操作方式与“Where”相同,但“Find”还检查ObjectContext以查看是否有任何添加的实体满足给定谓词。这允许您查找实体,即使它尚未保存到数据库中

Find返回一个IQueryable(of T),这样您就可以像使用任何其他LINQ操作符一样使用它

<Extension()>
Public Function Find(Of T As Class)(ByVal OSet As ObjectSet(Of T), _
       ByVal predicate As Expression(Of Func(Of T, Boolean))) _
       As System.Linq.IQueryable(Of T)

    'Check the object context for Added objects first.
    Dim AddedContextObjects = OSet.Context.ObjectStateManager _
                        .GetObjectStateEntries(EntityState.Added) _
                        .Select(Function(entity) entity.Entity).OfType(Of T)()


    Dim Cpredicate = predicate.Compile
    Dim MatchingObjects As New List(Of T)

    For Each TObj As T In AddedContextObjects
        If Cpredicate.Invoke(TObj) Then
            MatchingObjects.Add(TObj)
        End If
    Next

    'Now include a query to retrieve objects from the DB.
    Dim DBObjects = OSet.Where(predicate)

    If MatchingObjects.Count > 0 Then
        'We found some added objects in the context.
        'We want to return these objects as well as any Objects in DB
        'that satisfy the predicate.
        Return MatchingObjects.Union(DBObjects).AsQueryable
    Else
        'We didn't find any added objects in the context,
        'so we just return the DB query.
        Return DBObjects
    End If

End Function

公共函数Find(属于T类)(ByVal OSet作为对象集(属于T类)_
ByVal谓词作为表达式(Func的(T的,布尔的)))_
As系统Linq.IQueryable(属于T)
'首先检查添加对象的对象上下文。
Dim AddedContextObjects=OSet.Context.ObjectStateManager_
.GetObjectStateEntries(EntityState.Add)_
。选择(功能(实体)实体。实体)。类型(共T)()
Dim Cpredicate=predicate.Compile
尺寸匹配对象作为新列表(共T个)
对于AddedContextObjects中的每个TObj作为T
如果Cpredicate.Invoke(TObj),则
匹配对象添加(TObj)
如果结束
下一个
'现在包括一个从数据库检索对象的查询。
Dim DBObjects=OSet.Where(谓词)
如果MatchingObjects.Count>0,则
'我们在上下文中找到了一些添加的对象。
'我们希望返回这些对象以及数据库中的任何对象
满足谓词的。
返回MatchingObjects.Union(DBObjects.AsQueryable)
其他的
'我们没有在上下文中找到任何添加的对象,
'因此我们只返回DB查询。
返回DBObjects
如果结束
端函数

我也处于同样的情况。我写了这个扩展方法,至少对我来说解决了这个问题(我的上下文中没有冲突的问题…)

公共静态IEnumerable whereincluded(此对象集,表达式谓词),其中T:class
{
var dbResult=set.Where(谓词);
var offlineResult=set.Context.ObjectStateManager.GetObjectStateEntries(EntityState.Added).Select(entry=>entry.Entity).OfType().Where(predicate.Compile());
返回offlineResult.Union(dbResult);
}

新添加的对象位于本地数据源中,因为它尚未在数据库中持久化

所以你可以说:

EntityObject search = ents.EntityObject.FirstOrDefault(o => o.Id == theId) ??
                      ents.EntityObject.Local.FirstOrDefault(o => o.Id == theId);

下面的扩展方法是DbSet


顺便说一句:我喜欢仿制药

实体框架6

根据Dbset,始终对数据库进行查询

请注意,DbSet和IDbSet总是针对数据库创建查询 并且始终涉及到数据库的往返,即使 返回的实体在上下文中已存在。执行查询 在以下情况下,针对数据库:

它由foreach(C#)或For Each(Visual Basic)枚举 陈述它由收集操作(如ToArray)枚举, ToDictionary,或ToList。LINQ运算符(如First或Any)是 在最外层指定
EntityObject search = ents.EntityObject.FirstOrDefault(o => o.Id == theId) ??
                      ents.EntityObject.Local.FirstOrDefault(o => o.Id == theId);
public static T TryAttach<T>(this DbSet<T> dbSet, T entity, Expression<Func<T, bool>> predicate) where T : class
{
     T found = dbSet.Local.SingleOrDefault(predicate.Compile());
     if (found == null) dbSet.Attach(entity);
     return found ?? entity;
}
contextInstance.MyEntity.TryAttach(entityInstance, e => e.ID == entityInstance.ID);
await dbContext.Entity
      .Where(e => e.Title.Contains("Text"))
      .LoadAsync();

var locaEntities = dbContext.Entity.Local;

dbContext.Entity.Add(new Entity {});

// call save post atomic operation is finished.
await dbContext.SaveChangesAsync();