foreach循环只返回具有多个记录的Linq查询后的第一个记录
本文关键字:记录 Linq 查询 第一个 循环 返回 foreach | 更新日期: 2023-09-27 18:12:13
我有一个针对第三方提供的数据库运行的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 Profiler以确保正在运行的查询返回正确的结果,并且它确实。
foreach循环是这样的(Convert是由于数据库设计非常糟糕,数据类型非常不一致):
foreach (var record in valuationQuery)
{
int CurrentValType = Convert.ToInt32(record.ValueTypeID);
string FieldName = "Value";
if (MPLower.MileagePointID >= 1 && MPLower.MileagePointID <= MaxMileagePoints)
{
FieldName = "Value" + MPLower.MileagePointID.ToString().Trim();
MPLower.MileagePointPounds[CurrentValType] = Convert.ToInt32(record.GetType().GetProperty(FieldName).GetValue(record, null));
}
if (MPHigher.MileagePointID >= 1 && MPHigher.MileagePointID <= MaxMileagePoints)
{
FieldName = "Value" + MPHigher.MileagePointID.ToString().Trim();
MPHigher.MileagePointPounds[CurrentValType] = Convert.ToInt32(record.GetType().GetProperty(FieldName).GetValue(record, null));
}
}
我是c#新手(我继承了一些代码),所以我意识到这可能是我做过或没有做过的愚蠢的事情!!请问有人能帮忙吗?
标识图
使用orm时的一个常见问题(好吧,也许不是很常见,但可能会发生)是您期望返回不同记录的查询最终返回同一记录的多个副本。这通常是由ORM的身份映射引起的。下面是它的工作原理的快速概述。
身份映射本质上是一个对象缓存,基于每个对象的主键。
当您向ORM请求具有特定主键的记录时,它将检查该记录是否已经存在于身份映射中。如果它已经存在,它将返回已经存在的记录。
这通常很方便,但有时也会出错。如果两个对象具有相同的主键,或者您没有指定主键是什么(强制ORM猜测),则身份映射无法区分它们,并且将始终返回第一个对象。
这个故事的寓意是,如果你看到同一记录的多个副本,总是要仔细检查你的主键。
在这个问题中,代码
select new
{
v.Value1,
v.Value2,
v.Value3,
... snip ...
v.Value14,
v.Value15,
v.ValueTypeID
};
可以工作,因为您正在使用select new{}投影来返回匿名类型,从而绕过身份映射。
select v
直接选择对象,这会使用身份映射,从而导致您看到的问题。