LINQ:强制转换为值类型'System.Int32',因为物化值为null

Mar*_*lef 5 c# t-sql linq sql-server entity-framework

在数据库上执行LINQ查询时出现以下错误:

强制转换为值类型'System.Int32',因为实例化值为null。

我相信这是因为其中一列返回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();
Run Code Online (Sandbox Code Playgroud)

我试图实现以下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;
Run Code Online (Sandbox Code Playgroud)

空值是AccreditationID列中的。这里是关系:

实体关系图

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

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

谢谢。

Iva*_*oev 4

(1) 我是否正确地将 T-SQL 查询转换为 LINQ?

是的,你做对了。

旁注(与主要问题无关):在执行left outer join. 一旦使用了into子句,用于访问实体记录的名称就超出了范围,并且可以重复使用,这使得查询的其余部分看起来相似,无论连接类型(innerleft outer)如何。例如

join ba in Program.db.BrandAccreditations on b.ProductBrandID equals ba.ProductBrandID into bax
from credJoins in bax.DefaultIfEmpty()
Run Code Online (Sandbox Code Playgroud)

可能

join ba in Program.db.BrandAccreditations on b.ProductBrandID equals ba.ProductBrandID into baJoin
from ba in baJoin.DefaultIfEmpty()
Run Code Online (Sandbox Code Playgroud)

如果删除into以下from行,它将变成inner join,反之亦然。

(2)当我实际上期望空值(因此左外连接)时,如何解决与空值相关的问题?

left join这是值类型字段的典型错误。实际上完整的错误消息包含解决方案:

结果类型的泛型参数或查询必须使用可以为 null 的类型

换句话说,找到来自righta 一侧的不可为空值类型字段left outer join,然后将它们转换为可空等效值。

对于你的情况,在这里:

select new { c.CompanyID, types.ProductTypeID, b.ProductBrandID, accreds.AccreditationID, s.AnimalName }
Run Code Online (Sandbox Code Playgroud)

这些字段是types.ProductTypeIDaccreds.AccreditationID,所以修复方法是(假设它们的类型是int):

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