LINQ查询返回多个第一个结果的副本

6
我正在尝试弄清楚为什么LINQ中的简单查询会返回奇怪的结果。
我在数据库中定义了一个视图。它基本上将几个其他表组合在一起并进行一些数据处理。实际上,除了处理大型数据集并可能有点慢之外,它并没有什么特别之处。
我想根据一个长整型查询这个视图。下面是两个示例查询,用于查询此视图。
var la = Runtime.OmsEntityContext.Positions.Where(p => p.AccountNumber == 12345678).ToList();

var deDa = Runtime.OmsEntityContext.Positions.Where(p => p.AccountNumber == 12345678).Select(p => new { p.AccountNumber, p.SecurityNumber, p.CUSIP }).ToList();

第一个查询应该返回一个列表。第二个查询将返回一组匿名对象列表。
当我在实体框架中执行这些查询时,第一个查询将返回一个结果列表,其中所有结果都完全相同。
第二个查询将返回数据,其中账号是我查询的账号,而其他值不同。这似乎是基于每个账号编号的,即如果我查询一个账号编号或另一个账号编号,则一个账户的所有头寸对象都具有相同的值(该账户的头寸列表中的第一个),而第二个账户将拥有一组具有相同值的头寸对象(同样是其头寸对象列表中的第一个)。
我可以编写SQL查询,其效果与任何两个EF查询相同。它们都返回正确数据的结果(例如四个结果),其中一个账号编号具有不同的证券编号。
为什么会发生这种情况???是否有什么我可能做错了的事情,以便如果我对上面的第一个查询有四个结果,则第一条记录的数据也会出现在2-4的对象中???
我无法理解会/可能导致这种情况发生的原因。我已经在Google上搜索了各种关键字,但没有看到任何人遇到这个问题。我们为Positions类分部分类出添加的功能(智能对象)和一些智能属性。甚至有一些构造函数提供了一些视图模型类型的支持。请求中没有调用任何这些内容(我确信99%)。但是,我们在整个应用程序中都使用了这种模式。
我唯一能想到的是EDMX中的映射有问题。如果EDMX中的“主键”实际上不是唯一的,那么是否有可能以这种方式发生,考虑到视图的构造方式?我认为导入此模型到EDMX中的开发人员让设计师自动选择了什么是唯一的。
任何帮助都将给一个疲惫的开发人员一些希望!

3
获取生成的 SQL 脚本,并在 Management Studio 中交互运行,以查看实际情况。 - Michael Haren
就像所说的那样,也许可以使用分析器来查看正在执行的 SQL。 - Jason Rowe
2个回答

13

针对这个问题的答案是:

确保您的实体键是唯一的!

在EDMX中生成的视图具有三个被标记为实体键的列/属性(我猜这些列组合起来形成了记录的唯一标识符)。

在我的查询中,这三列都是相同的。我想实体框架会崩溃,并将第一个记录放入所有后续记录,直到其中某个列发生更改(从而形成新的唯一“集”)。

现在我已经弄清楚了这一点,回顾一下最初使用这些信息的地方,发现首先应用了分组语句(数据是通过应用程序中的存储过程查询的)。分组展平了一个实体键列,使其始终保持唯一。这导致该位置的结果看起来很好。

我的解决办法是向此视图添加一个新列,只投影一个GUID(在SQL中使用NEWID())。问题是我不知道如何告诉EDMX使用这个新添加的属性作为映射视图的唯一实体键!

- 我将此关闭为已解决,因为我知道问题所在,并将在新问题中提出我的其他问题。感谢那些抽出时间回答的人提供的所有见解!


请告诉我们您是如何在视图或edmx中将其设置为PK的。 - C Sharper
嘿,伙计们,我希望我仍然可以访问这个代码库。在发布这个问题/答案后不久,我就离开了这个职位。自从我使用EF以来已经有一段时间了。在流畅的API中,这将是微不足道的。如果我记得正确,我删除了所有单独的键,以便在映射中没有组合键,而是使用视图中创建的GUID作为PK。 - Mike G

0

你尝试过这种语法吗?虽然不敢想象它会是原因,但谁知道呢...

using (var dc = new OmsEntityContext())
{
  var la = (from p in dc.Position
  where p.AccountNumber = "12345678"
  select p).ToList();
}

using (var dc = new OmsEntityContext())
{
  var deDa = (from p in dc.Position
  where p.AccountNumber = "12345678"
  select new {p.AccountNumber, p.SecurityNumber, p.CUSIP}).ToList();
}

</longShot>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接