LINQ: 因为实例化的值为空,所以将其转换为值类型'System.Int32'失败。

5
执行LINQ查询时,我遇到了以下错误:
“转换为值类型'System.Int32'失败,因为实例值为空。”
我认为这是因为其中一个列返回了null。以下是我的LINQ命令:
var facts = (from b in Program.db.ProductBrands
             join bm in Program.db.BrandManufacturers on b.ProductBrandID equals bm.ProductBrandID
             join c in Program.db.Companies on bm.ProductManufacturerID equals c.CompanyID
             join s in Program.db.AnimalSources on b.AnimalCode equals s.AnimalCode
             join ba in Program.db.BrandAccreditations on b.ProductBrandID equals ba.ProductBrandID into bax
             from credJoins in bax.DefaultIfEmpty()
             join a in Program.db.Accreditations on credJoins.AccreditationID equals a.AccreditationID into ax
             from accreds in ax.DefaultIfEmpty()
             join bt in Program.db.BrandTypes on b.ProductBrandID equals bt.BrandTypeID into btx
             from brandJoins in btx.DefaultIfEmpty()
             join t in Program.db.ProductTypes on brandJoins.ProductTypeID equals t.ProductTypeID into tx
             from types in tx.DefaultIfEmpty()
             select new { c.CompanyID, types.ProductTypeID, b.ProductBrandID, accreds.AccreditationID, s.AnimalName }).Distinct();

这是我尝试实现以下T-SQL查询的结果:
SELECT DISTINCT c.CompanyID, b.ProductBrandID, s.AnimalName, a.AccreditationID, t.ProductTypeID
FROM dbo.ProductBrand b
INNER JOIN dbo.BrandManufacturer bm ON b.ProductBrandID = bm.ProductBrandID
INNER JOIN dbo.Company c ON bm.ProductManufacturerID = c.CompanyID
INNER JOIN dbo.AnimalSource s ON b.AnimalCode = s.AnimalCode
LEFT OUTER JOIN dbo.BrandAccreditation ba ON b.ProductBrandID = ba.ProductBrandID
LEFT OUTER JOIN dbo.Accreditation a ON ba.AccreditationID = a.AccreditationID
LEFT OUTER JOIN dbo.BrandType bt ON b.ProductBrandID = bt.ProductBrandID
LEFT OUTER JOIN dbo.ProductType t ON bt.ProductTypeID = t.ProductTypeID;

nulls在AccreditationID列中。以下是关系:

实体关系图

我的问题实际上有两个部分:

  1. 我是否已正确将T-SQL查询转换为LINQ?
  2. 当我实际上希望出现nulls(因此是左外连接)时,如何解决与nulls相关的问题?

谢谢。


2
你是否将 Accreditations.AccreditationID 定义为 int??另一种选择可能是选择 AccreditationID = accreds?.AccreditationId 而不是简单地选择 accreds.AccredidationId - Rob
@Rob 我该怎么做? - Mark Micallef
@Rob,你的语法不太对。经过一些试错,我想出了这个:AccreditationID = (int?)accreds.AccreditationID - Mark Micallef
在概念模型中,您不需要使用连接来模拟SQL连接,概念模型或类将使用导航属性相互链接。 - Abhinav Galodha
1个回答

4

(1) 我正确地将我的T-SQL查询转换为LINQ了吗?

是的,你做得很正确。

一个小提示(与主要问题无关):在进行左外连接时没有必要使用不同的名称。一旦使用了into子句,用于访问实体记录的名称就超出了作用域并且可以被重复使用,这使得查询的其余部分看起来类似,无论是inner还是left outer连接类型。例如:

join ba in Program.db.BrandAccreditations on b.ProductBrandID equals ba.ProductBrandID into bax
from credJoins in bax.DefaultIfEmpty()

可能是

join ba in Program.db.BrandAccreditations on b.ProductBrandID equals ba.ProductBrandID into baJoin
from ba in baJoin.DefaultIfEmpty()

如果您删除into和接下来的from行,则会变成inner join,反之亦然。
(2)当我实际上期望nulls(因此是左外连接)时,如何解决与nulls相关的问题?
这是使用left join值类型字段时的典型错误。实际上,完整的错误消息包含了解决方案:
结果类型的泛型参数或查询必须使用可空类型
换句话说,找到来自left outer join右侧的非可空值类型字段,并将它们转换为可空等效项即可。
在您的情况下,在这里:
select new { c.CompanyID, types.ProductTypeID, b.ProductBrandID, accreds.AccreditationID, s.AnimalName }

需要翻译的内容如下:

这样的字段包括types.ProductTypeIDaccreds.AccreditationID,因此修复方法是(假设它们是int类型):

select new { c.CompanyID, (int?)types.ProductTypeID, b.ProductBrandID, (int?)accreds.AccreditationID, s.AnimalName }

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