我正在开发一个小应用程序,它允许用户创建单词列表,用户可以为列表提供名称。我设置程序以利用工作单元模式。我希望用户能够进行他们想要的所有CRUD更改,然后当用户准备好更新数据库时,单击“保存更改”按钮以执行Context.SaveChanges()并进行所有更改。
我正在使用Entity Framework和Repository&启用了延迟加载的工作单元模式。列表和单词类都是映射到数据模型的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对象来实现它。任何帮助将不胜感激,或请指出我正确的方向。
感谢。
答案 0 :(得分:2)
这就是EF的表现方式。您的Find
和FindAll
访问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;
}