我使用实体框架有以下问题。我使用IOC和我的DBContext作为每个请求的实例。我想插入' Team'对象到我的数据库中。在某个请求中,有一个循环将多个团队插入数据库。在我添加它之前,我检查团队是否已经存在。如果它不存在,则可以插入。 这些插入发生在同一个上下文中,最后我保存我的更改(SaveChanges)现在出现以下问题:
要获取我的IdbSet,请执行以下操作:_context.Set<TEntity>()
插入TEntity后,_context.Set<TEntity>()
不包含我插入的对象。如何确保实体框架在同一范围内跟踪插入?
编辑: 示例 首先,我添加我的团队
_context.Set<Team>().Add(entity);`
然后我搜索它,但它不在列表中
_context.Set<Team>().Where(p => p.Name.Equals(name, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
答案 0 :(得分:1)
编辑以反映对EF行为的担忧:
是这种行为的设计。 EF查询将针对DB而不是本地上下文(未保存)实体执行。您仍然可以通过一些棘手的方式选择本地上下文缓存。但是我不推荐这个解决方案。
建议的解决方案:
在您的实体的服务器端创建唯一键/约束。当您尝试插入(或更新)副本时,SaveChanges将出现异常。没有其他方法可以确保没有重复,除了错误的解决方案#2 resoulution
回到原始问题的术语,概念性答案是:以自然和集中的方式跟踪您的INSERTS的SQL Server。如果集中式方式术语没有意义,请阅读两个提出了不好的解决方案
糟糕的解决方案#1:
重复问题在请求和更多内容中仍然有效:跨会话。您可以决定将您的上下文实例保留在请求中,因此上下文将包含prev插入的实体。这是一个非常糟糕的主意。首先,无法保证过去的会话或当前并发用户不会插入重复项。我们可以放心地忘记这一点。
糟糕的解决方案#2:
这是一个危险的行为,因为它的不当行为并不那么明显。在 virgin 会话中,首先检查实体是否存在,如果不是,则插入。如果实体不存在,这将向服务器进行2次往返(通常情况下我认为)。这绝对是一个缺点。但这不是主要问题。默认情况下,这两个操作不是原子操作,因此在检查不存在但插入之前,其他会话/用户可以插入同一个实体,因此您要结束插入重复操作。
错误的解决方案#2解决方案:您可以在一个事务中进行检查和更新以使其成为原子,但您的连接/事务隔离级别仍然必须在(SQL)SERIALIZABLE隔离级别(在SQL Server中最高),这使我们走得太远,因为它在客户端很复杂,并且在服务器端有严重的性能缺陷。
答案 1 :(得分:1)
在将更改更改为数据库之前,您可以使用Set<Team>().Local.Where(...)
查找插入的对象。
然而,这只是ORM的糟糕设计(也是一个典型的问题)。
您正在使用ORM,但仍在使用&#34;数据库思维&#34;,您正在使用DbSet
作为对象集合。
尝试认为你在这种情况下没有做任何与数据库有关的事情(想想你是做对象而忘记了EF的一刻)......你可能只有{{{{ 1}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}从数据库中检索 - 使用EF-,在内存上创建新内容,从磁盘读取或诸如此类的东西)并在处理它们时传递该列表。
然后使用实体框架坚持对象,而不是处理它们。田田,问题解决了。
如果你认为EF是一个&#34;数据库持久化和检索对象框架&#34;而不是你用&#34;做你的逻辑的&#34;对象集合,你就会...通过非常肮脏的解决方法为自己节省大量未来的问题和警告(包括这一点)。