我有一个linq查询在VS2010和VS2012系统中运行良好,在系统中最初编写代码,但是当提交到SVN并提取到新系统时,代码没有构建。相同的代码在2个系统中工作正常但在其他3个系统中都失败,每个系统都有VS2012,.NET Framework 4.0(目标框架)。
不确定代码有什么问题。我理解编写的代码有错误并且写得非常错误。
以下是样本linq查询在VS2010中正常工作但在VS2012中失败。
from d in db.VacancyCandidates
join c in db.Candidates on new
{ CandidateId = d.CandidateId, CandidateType = d.CandidateType}
equals new { CandidateId = c.CandidateId, CandidateType = c.CanidateTypeId }
........Rest query ......
上面的查询d.CandidateType
为Nullable<int>
,c.CanidateTypeId
为int。
我查看了以下post,如果我将d.CandidateType
更改为d.CandidateType.Value
,则代码构建正确。
我的问题是为什么代码在VS2010中构建而在VS2012中不在我的机器中?
有关编译器的更多信息:
PLS。知道在所有系统上,项目的目标框架仅为4.0。使用CSC /?
命令C:\Windows\Microsoft.NET\Framework64\V4.0.3.319\
答案 0 :(得分:1)
我无法谈论它在VS2010中的原因,很可能是旧版本的C#编译器。
现在编译器将使用引用成员的Type
和Name
来确定它需要生成哪种匿名类型。
它将尝试匹配具有完全相同签名的任何匿名类型。因此new { A = "1" }
和new { A = "2" }
具有相同的类型,但new { A = "1" }
和new { A = 1 }
不会。
它将生成的第一个匿名类型可能分别有CandidateId
和CandidateType
类型int
和int?
。
对于第二个匿名类型,它将验证是否有任何其他类型具有完全相同的签名。这不是这种情况,因为CandidateType
在第二个初始化程序中的类型为int
。
如上所述,为了使签名匹配,您需要确保类型对齐。
from d in db.VacancyCandidates
join c in db.Candidates on new { CandidateId = d.CandidateId, CandidateType = d.CandidateType}
equals new { CandidateId = c.CandidateId, CandidateType = (int?)c.CanidateTypeId }
请注意,当值为Nullable<>
时,使用null
类型的值将失败。因此,您提出的转发d.CandidateType.Value
的解决方案可能是危险的。
它“可能”是危险的,因为它取决于你是通过Linq-to-SQL还是EntityFramework直接查询数据库,还是在内存中工作,行为是不同的。
使用.Value
null
的{{1}}在作为内存lambda执行时会抛出Nullable<>
,但是如果它被转换为SQL查询则不会,因为InvalidOperationException
非常聪明,可以解决这个问题。