C# 具有原始存储过程的Linq to实体返回重复的数据副本

C# 具有原始存储过程的Linq to实体返回重复的数据副本,c#,linq,entity-framework,sql-server-2008-r2,linq-to-entities,C#,Linq,Entity Framework,Sql Server 2008 R2,Linq To Entities,与SQL Server 2008R2的接口: 我有一个linq表达式: IQueryable<xxx> xxxResult = (from t in _context.xxxx.AsNoTracking().Include("yyy") where t.zzz >= lowNumber && t.zzz <= highNumber && t.qqq == someValue

与SQL Server 2008R2的接口:

我有一个linq表达式:

IQueryable<xxx> xxxResult =
     (from t in _context.xxxx.AsNoTracking().Include("yyy")
     where t.zzz >= lowNumber
           && t.zzz <= highNumber
           && t.qqq == someValue
     select t);            
除了一个问题外,这似乎有效。当在linq查询表上迭代时,一切都很顺利。但是,当我使用存储过程时,我会得到重复的记录

例如,如果我有一个xxx记录,其中在一个集合中包含3条yyy记录,那么我会从linq表达式中获得一条xxx记录,并且正如预期的那样,它在内部集合中包含3条yyy记录

对于同一数据集,存储过程在查询表上迭代返回三条xxx记录,每条记录都包含相同的3条yyy记录

同样,存储过程执行与linq表达式生成的SQL完全相同的SQL

为什么呢?有什么想法吗


(同样是EF的新手,请原谅术语上的错误。)

我相信EF根据您定义的主键将您的结果视为重复。在EF5中,这将在唯一定义实体的字段上使用“实体键”属性来定义(多部分主键将在多个字段上设置此属性)

如果您的过程返回的记录与它已经返回的记录相匹配(仅基于主键字段),那么它将返回对上一条记录的引用

LINQ表达式使用.AsNoTracking,这将阻止这种缓存行为

我猜使用存储过程的.AsNoTracking()是在缓存后发生的,没有您想要的效果

确保在模型上正确设置了主键

下面有一篇文章从一个角度描述了这种行为: 这应该与您看到的存储过程类似


在代码优先中,您可能会使用[Key]注释来指定您的唯一键:

TSQL,用于存储过程。它是IQueryable为linq表达式生成的SQL的精确副本。我在两个表中正确定义了键。它们都使用相同的组合键,并且使用正确的顺序定义键。(包含的表在复合键中有第三个元素,在基表中不存在,但它被排序为第三个元素)。jepsonblog的文章和我看到的不太一样。例如,我看到的是,如果我有:A,1a,2a,3,linq表达式返回一条记录A(1,2,3)。存储过程返回三条记录,它们都是(1,2,3)。linq表达式是我所期望的。我不认为以后会发生AsNoTracking。两者都返回完全相同的数据集,并且直到我使用第一个迭代器时才会执行该过程<代码>context.Set().AsNoTracking().FromSql(“executedbo.sp_Get{0}”,id)这在EF core中发生。
IQueryable<xxx> xxxResult = 
    _context.xxxx.SqlQuery("GetData @p0, @p1, @p2",  someValue, lowNumber, highNumber)
                 .AsNoTracking().AsQueryable();