在具有多个记录的Linq查询之后,foreach循环仅返回第一条记录

我有一个针对第三方提供的数据库运行的Linq2SQL查询。 查询的主要部分如下所示:

var valuationQuery = from v in context.Valuations where v.ModelId == QualifiedModelId.ModelId && v.QualifyModelId == QualifiedModelId.Qualifier && v.LanguageCode == QualifiedModelId.LanguageCode && v.Edition == Data.Meta.Edition.CurrentEdition.Date && v.RegDate == yearReg.RegistrationDate && v.ValTypeDescription == "Normal" && v.MileageBandID == MileageBand 

当我用foreach循环环绕它时,它会工作或失败,具体取决于最后的选择。 当select指定所有这样的字段时……

  select new { v.Value1, v.Value2, v.Value3, ... snip ... v.Value14, v.Value15, v.ValueTypeID }; 

……它正常工作。 当我执行以下操作时,循环会迭代正确的次数,但每次都会返回第一条记录:

  select v; 

我希望能够在不指定名称的情况下选择所有字段,以防供应商添加更多字段(它们实际上称为“Value1”到“Value15”),这意味着我可以在代码中更改一个常量并更新DBML和所有相关代码都将从正确的字段数量中查找。 这个查询(和类似的查询)在各个地方使用,所以我在寻找未来最少的努力!

我已经运行SQL事件探查器以确保正在运行的查询返回正确的结果,并且确实如此。

foreach循环是这样的(转换是由于设计非常糟糕的数据库具有非常不一致的数据类型):

  foreach (var record in valuationQuery) { int CurrentValType = Convert.ToInt32(record.ValueTypeID); string FieldName = "Value"; if (MPLower.MileagePointID >= 1 && MPLower.MileagePointID = 1 && MPHigher.MileagePointID <= MaxMileagePoints) { FieldName = "Value" + MPHigher.MileagePointID.ToString().Trim(); MPHigher.MileagePointPounds[CurrentValType] = Convert.ToInt32(record.GetType().GetProperty(FieldName).GetValue(record, null)); } } 

我是C#的新手(我inheritance了一些代码),所以我意识到这可能是我做过或做过的愚蠢! 请任何人可以帮忙吗?

身份地图

使用ORM时常见的问题(好的,可能不常见,但可能发生)是您希望返回不同记录的查询最终会返回同一记录的多个副本。 这通常是由ORM的身份地图引起的。 以下是对其正常工作方式的快速概述。

身份映射本质上是一个对象缓存,基于每个对象的主键。

当您向ORM询问具有某个主键的记录时,它将检查该记录是否已存在于身份映射中。 如果它已经存在,它将返回现有记录。

这通常非常方便,但有时会出错。 如果两个对象具有相同的主键,或者您没有指定主键是什么(强制ORM猜测),则身份映射无法区分它们,并且将始终返回第一个。

这个故事的寓意是,如果你看到同一个记录的多个副本,你不应该仔细检查你的主键!


在这个问题中,代码

  select new { v.Value1, v.Value2, v.Value3, ... snip ... v.Value14, v.Value15, v.ValueTypeID }; 

之所以有效,是因为您使用select new {}投影返回匿名类型,该类型绕过了身份映射。

  select v 

直接选择对象,使用身份地图,导致您看到的问题。