与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生成了SQL,SQL Server生成了一个糟糕的计划,而且,由于我无法添加索引/连接提示,因此我创建了一个存储过程,该程序包含了上述Linq表达式生成的SQL。
我知道我应该能够通过Entity Framework访问存储过程,但是我使用的是之前使用非常轻量级的代码优先实现的项目(例如,没有.edmx
文件)和我对整个EF事物都不熟悉,并且不知道如何将新程序绑定到EF。我知道可以做到,但我试图直接调用该程序。
我解决了这个问题:
IQueryable<xxx> xxxResult =
_context.xxxx.SqlQuery("GetData @p0, @p1, @p2", someValue, lowNumber, highNumber)
.AsNoTracking().AsQueryable();
这似乎有效,除了一个问题。当遍历linq可查询时,一切都在游泳。但是,当我使用存储过程时,我得到重复的记录。
例如,如果我有一个包含3个yyy记录的xxx记录,我会从linq表达式中获取单个xxx记录,并且正如预期的那样,它包含内部集合中的3个yyy记录。
对于同一数据集,迭代可查询的存储过程返回三个xxx记录,其中每个记录包含相同的3个yyy记录。
同样,存储过程执行与linq表达式生成的完全相同的SQL。
为什么?有什么想法吗?
(同样,对EF来说是新手,所以请原谅术语中的错误。)
答案 0 :(得分:0)
我相信EF会根据您定义的主键将结果视为重复。在EF5中,这将使用&#34;实体密钥&#34;来定义。唯一定义实体的字段上的属性(多部分主键将在多个字段上设置此项)。
如果您的过程返回的记录与已经返回的记录匹配(基于主键字段的soley),那么它将返回对前一记录的引用。
你的LINQ表达式使用.AsNoTracking来防止这种缓存行为。
我猜测使用存储过程的.AsNoTracking()是在缓存之后发生的,并且没有你想要的效果。
确保在模型上正确设置了主键。
这是一篇用视图描述行为的文章: http://jepsonsblog.blogspot.in/2011/11/enitity-framework-duplicate-rows-in.html应与您在存储过程中看到的内容类似。
在Code First中,您可以使用[Key]注释指定您的唯一键:http://msdn.microsoft.com/en-us/data/jj591583.aspx