在IRepository <t> .FindAll()</t>中未返回EntityState.Added的实体

时间:2011-08-21 02:53:20

标签: c# entity-framework repository-pattern unit-of-work

我正在开发一个小应用程序,它允许用户创建单词列表,用户可以为列表提供名称。我设置程序以利用工作单元模式。我希望用户能够进行他们想要的所有CRUD更改,然后当用户准备好更新数据库时,单击“保存更改”按钮以执行Context.SaveChanges()并进行所有更改。

我正在使用Entity Framework和Repository&amp;启用了延迟加载的工作单元模式。列表和单词类都是映射到数据模型的POCO,而数据模型又是从数据库映射的。

我的添加代码:

_unitOfWork.ListRepository.Add(newList);

ListRepository.Add方法:

public void Add(T newEntity)
{
    _objectSet.AddObject(newEntity);
}

稍后我收到一条带有消息的InvalidOperationException:Sequence不包含任何元素。

_unitOfWork.ListRepository.Find(l => l.Name == currentName).Single();

我知道为什么我会得到那个例外,因为我应该使用SingleOrDefault()来保证安全。但是,我知道我正在寻找的实体存在于上下文中的某些位置。我的猜测是我没有在正确的地方搜索。

这是摩擦(或我缺乏知识):

在调试期间,我在上面的_unitOfWork.ListRepository.Add(newList)代码上放了一个断点。在一个Step-Over之后,我去了立即窗口并做了以下事情:

?_unitOfWork.ListRepository.FindAll().Count();
1

“1”应该是“2”

ListRepository.FindAll()方法:

public IQueryable<T> FindAll()
{
    return _objectSet;
}

我已经跟踪了我的代码,我只是初始化了一次_unitOfWork对象。我在存储库中公开了ObjectSet.Context.ObjectStateManager,当调试中出现异常助手时,我可以转到立即窗口并执行:

_unitOfWork.ListRepository.GetObjectStateManager()
    .GetObjectStateEntries(EntityState.Added).Count();
1

所以,我知道实体在那里,但我不知道如何使用_unitOfWork或ListRepository对象来实现它。任何帮助将不胜感激,或请指出我正确的方向。

感谢。

1 个答案:

答案 0 :(得分:2)

这就是EF的表现方式。您的FindFindAll访问ObjectSet实例。这将始终对数据库进行查询 - 它对已创建但尚未插入数据库的实体不执行任何操作,并且它们不能作为返回结果的一部分。

要获取尚未保留的实体,您必须在ObjectStateManager中搜索。您可以将其添加到存储库以允许搜索单个实体。它将首先搜索内部EF存储,如果找不到实体,它将搜索数据库:

private T SearchStateManager(Expression<Func<T, bool>> searchCriteria)
{
    return _context.ObjectStateManager.GetObjectStateEntries(~EntityState.Detached)
                                      .Where(e => !e.IsRelationship)
                                      .Select(e => e.Entity)
                                      .OfType<T>()
                                      .SingleOrDefault(searchCriteria.Compile());
} 

public T Single(Expression<Func<T, bool>> searchCriteria)
{
    T entity = SearchStateManager(searchCriteria);
    if (entity == null)
    {
        entity = _objectSet.SingleOrDefault(searchCriteria);
    }

    return entity;
}