如何修复 FirstOrDefault 在 Linq 中返回 Null
How to fix FirstOrDefault returning Null in Linq
我的 Linq 查询不断在 FirstOrDefault 上返回空错误
The cast to value type 'System.Int32' failed because the materialized value is null
因为它无法在 ClinicalReading Table 的 ClinicalAssetID 上找到任何匹配的记录,很公平!
但是如果 table 没有匹配的条目,我希望我的详细信息页面中的字段显示为空白。
但是使用order by function时如何处理null问题呢?
当前代码:
var ClinicalASSPATINCVM = (from s in db.ClinicalAssets
join cp in db.ClinicalPATs on s.ClinicalAssetID equals cp.ClinicalAssetID into AP
from subASSPAT in AP.DefaultIfEmpty()
join ci in db.ClinicalINSs on s.ClinicalAssetID equals ci.ClinicalAssetID into AI
from subASSINC in AI.DefaultIfEmpty()
join co in db.ClinicalReadings on s.ClinicalAssetID equals co.ClinicalAssetID into AR
let subASSRED = AR.OrderByDescending(subASSRED => subASSRED.MeterReadingDone).FirstOrDefault()
select new ClinicalASSPATINCVM
{
ClinicalAssetID = s.ClinicalAssetID,
AssetTypeName = s.AssetTypeName,
ProductName = s.ProductName,
ModelName = s.ModelName,
SupplierName = s.SupplierName,
ManufacturerName = s.ManufacturerName,
SerialNo = s.SerialNo,
PurchaseDate = s.PurchaseDate,
PoNo = s.PoNo,
Costing = s.Costing,
TeamName = s.TeamName,
StaffName = s.StaffName,
WarrantyEndDate = subASSPAT.WarrantyEndDate,
InspectionDate = subASSPAT.InspectionDate,
InspectionOutcomeResult = subASSPAT.InspectionOutcomeResult,
InspectionDocumnets = subASSPAT.InspectionDocumnets,
LastTypeofInspection = subASSINC.LastTypeofInspection,
NextInspectionDate = subASSINC.NextInspectionDate,
NextInspectionType = subASSINC.NextInspectionType,
MeterReadingDone = subASSRED.MeterReadingDone,
MeterReadingDue = subASSRED.MeterReadingDue,
MeterReading = subASSRED.MeterReading,
MeterUnitsUsed = subASSRED.MeterUnitsUsed,
FilterReplaced = subASSRED.FilterReplaced
}).FirstOrDefault(x => x.ClinicalAssetID == id);
试过这个但不起作用
.DefaultIfEmpty(new ClinicalASSPATINCVM())
.FirstOrDefault()
错误是:
CS1929 'IOrderedEnumerable<ClinicalReading>' does not contain a definition for 'DefaultIfEmpty' and the best extension method overload 'Queryable.DefaultIfEmpty<ClinicalASSPATINCVM>(IQueryable<ClinicalASSPATINCVM>, ClinicalASSPATINCVM)' requires a receiver of type 'IQueryable<ClinicalASSPATINCVM>'
感觉有点接近这个但是还是有错误
let subASSRED = AR.OrderByDescending(subASSRED => (subASSRED.MeterReadingDone != null) ? subASSRED.MeterReadingDone : String.Empty).FirstOrDefault()
错误:
CS0173 Type of conditional expression cannot be determined because there is no implicit conversion between 'System.DateTime?' and 'string'
你的问题是因为你的 DefaultIfEmpty 被执行为 AsQueryable。执行它 AsEnumerable
它将起作用:
// create the default element only once!
static readonly ClinicalAssPatInVcm defaultElement = new ClinicalAssPatInVcm ();
var result = <my big linq query>
.Where(x => x.ClinicalAssetID == id)
.AsEnumerable()
.DefaultIfEmpty(defaultElement)
.FirstOrDefault();
这不会导致性能下降!
数据库管理系统针对数据选择进行了极度优化。数据库查询中速度较慢的部分之一是将所选数据传输到本地进程。因此,让 DBMS 完成大部分选择是明智的,只有在您知道只有您真正打算使用的数据后,才将数据移动到您的本地进程。
在您的情况下,您最多需要 DBMS 中的一个元素,如果什么都没有,则您想使用默认对象。
AsQueryable
将以智能方式将所选数据移动到您的本地进程,可能是每个 "page" 所选数据。
页面大小是一个很好的折衷方案:不要太小,这样您就不必经常请求下一页;不要太大,这样你就不会转移比实际使用更多的物品。
此外,由于 Where
语句,您无论如何都最多期望一个元素。因此获取完整的 "page" 是没有问题的,页面将只包含一个元素。
获取页面后,DefaultIfEmpty
检查页面是否为空,如果是,returns 包含 defaultElement
的序列。如果没有,它 returns 完整的页面。
在 DefaultIfEmpty 之后你只需要第一个元素,这就是你想要的。
原来的错误意思是ClinicalASSPATINCVM
class的以下一些属性——MeterReadingDone
、MeterReadingDue
、MeterReading
、MeterUnitsUsed
,或者 FilterReplaced
的类型是 int
。
记住这里subASSRED
let subASSRED = AR.OrderByDescending(subASSRED => subASSRED.MeterReadingDone).FirstOrDefault()
可能是null
(无对应记录)。
现在看这部分投影:
MeterReadingDone = subASSRED.MeterReadingDone,
MeterReadingDue = subASSRED.MeterReadingDue,
MeterReading = subASSRED.MeterReading,
MeterUnitsUsed = subASSRED.MeterUnitsUsed,
FilterReplaced = subASSRED.FilterReplaced
如果那是 LINQ to Objects,所有这些都会在运行时产生 NRE(空引用异常)。在 LINQ to Entities 中,它被转换并执行为 SQL。 SQL 对 subASSRED.SomeProperty
这样的表达式没有问题,因为 SQL 自然支持 NULL
,即使 SomeProperty
通常不允许 NULL
。因此 SQL 查询正常执行,但现在 EF 必须将结果具体化为对象,而 C# 对象 属性 是 not 可为空的,因此出现了有问题的错误。
要解决它,请找到 int
属性(es) 并在查询中使用以下模式:
SomeIntProperty = (int?)subASSRED.SomeIntProperty ?? 0 // or other meaningful default
或将接收对象 属性 类型更改为 int?
并保持原始查询不变。
对任何不可为 null 的类型执行相同的操作 属性,例如DateTime
、double
、decimal
、Guid
等
我的 Linq 查询不断在 FirstOrDefault 上返回空错误
The cast to value type 'System.Int32' failed because the materialized value is null
因为它无法在 ClinicalReading Table 的 ClinicalAssetID 上找到任何匹配的记录,很公平!
但是如果 table 没有匹配的条目,我希望我的详细信息页面中的字段显示为空白。
但是使用order by function时如何处理null问题呢?
当前代码:
var ClinicalASSPATINCVM = (from s in db.ClinicalAssets
join cp in db.ClinicalPATs on s.ClinicalAssetID equals cp.ClinicalAssetID into AP
from subASSPAT in AP.DefaultIfEmpty()
join ci in db.ClinicalINSs on s.ClinicalAssetID equals ci.ClinicalAssetID into AI
from subASSINC in AI.DefaultIfEmpty()
join co in db.ClinicalReadings on s.ClinicalAssetID equals co.ClinicalAssetID into AR
let subASSRED = AR.OrderByDescending(subASSRED => subASSRED.MeterReadingDone).FirstOrDefault()
select new ClinicalASSPATINCVM
{
ClinicalAssetID = s.ClinicalAssetID,
AssetTypeName = s.AssetTypeName,
ProductName = s.ProductName,
ModelName = s.ModelName,
SupplierName = s.SupplierName,
ManufacturerName = s.ManufacturerName,
SerialNo = s.SerialNo,
PurchaseDate = s.PurchaseDate,
PoNo = s.PoNo,
Costing = s.Costing,
TeamName = s.TeamName,
StaffName = s.StaffName,
WarrantyEndDate = subASSPAT.WarrantyEndDate,
InspectionDate = subASSPAT.InspectionDate,
InspectionOutcomeResult = subASSPAT.InspectionOutcomeResult,
InspectionDocumnets = subASSPAT.InspectionDocumnets,
LastTypeofInspection = subASSINC.LastTypeofInspection,
NextInspectionDate = subASSINC.NextInspectionDate,
NextInspectionType = subASSINC.NextInspectionType,
MeterReadingDone = subASSRED.MeterReadingDone,
MeterReadingDue = subASSRED.MeterReadingDue,
MeterReading = subASSRED.MeterReading,
MeterUnitsUsed = subASSRED.MeterUnitsUsed,
FilterReplaced = subASSRED.FilterReplaced
}).FirstOrDefault(x => x.ClinicalAssetID == id);
试过这个但不起作用
.DefaultIfEmpty(new ClinicalASSPATINCVM())
.FirstOrDefault()
错误是:
CS1929 'IOrderedEnumerable<ClinicalReading>' does not contain a definition for 'DefaultIfEmpty' and the best extension method overload 'Queryable.DefaultIfEmpty<ClinicalASSPATINCVM>(IQueryable<ClinicalASSPATINCVM>, ClinicalASSPATINCVM)' requires a receiver of type 'IQueryable<ClinicalASSPATINCVM>'
感觉有点接近这个但是还是有错误
let subASSRED = AR.OrderByDescending(subASSRED => (subASSRED.MeterReadingDone != null) ? subASSRED.MeterReadingDone : String.Empty).FirstOrDefault()
错误:
CS0173 Type of conditional expression cannot be determined because there is no implicit conversion between 'System.DateTime?' and 'string'
你的问题是因为你的 DefaultIfEmpty 被执行为 AsQueryable。执行它 AsEnumerable
它将起作用:
// create the default element only once!
static readonly ClinicalAssPatInVcm defaultElement = new ClinicalAssPatInVcm ();
var result = <my big linq query>
.Where(x => x.ClinicalAssetID == id)
.AsEnumerable()
.DefaultIfEmpty(defaultElement)
.FirstOrDefault();
这不会导致性能下降!
数据库管理系统针对数据选择进行了极度优化。数据库查询中速度较慢的部分之一是将所选数据传输到本地进程。因此,让 DBMS 完成大部分选择是明智的,只有在您知道只有您真正打算使用的数据后,才将数据移动到您的本地进程。
在您的情况下,您最多需要 DBMS 中的一个元素,如果什么都没有,则您想使用默认对象。
AsQueryable
将以智能方式将所选数据移动到您的本地进程,可能是每个 "page" 所选数据。
页面大小是一个很好的折衷方案:不要太小,这样您就不必经常请求下一页;不要太大,这样你就不会转移比实际使用更多的物品。
此外,由于 Where
语句,您无论如何都最多期望一个元素。因此获取完整的 "page" 是没有问题的,页面将只包含一个元素。
获取页面后,DefaultIfEmpty
检查页面是否为空,如果是,returns 包含 defaultElement
的序列。如果没有,它 returns 完整的页面。
在 DefaultIfEmpty 之后你只需要第一个元素,这就是你想要的。
原来的错误意思是ClinicalASSPATINCVM
class的以下一些属性——MeterReadingDone
、MeterReadingDue
、MeterReading
、MeterUnitsUsed
,或者 FilterReplaced
的类型是 int
。
记住这里subASSRED
let subASSRED = AR.OrderByDescending(subASSRED => subASSRED.MeterReadingDone).FirstOrDefault()
可能是null
(无对应记录)。
现在看这部分投影:
MeterReadingDone = subASSRED.MeterReadingDone,
MeterReadingDue = subASSRED.MeterReadingDue,
MeterReading = subASSRED.MeterReading,
MeterUnitsUsed = subASSRED.MeterUnitsUsed,
FilterReplaced = subASSRED.FilterReplaced
如果那是 LINQ to Objects,所有这些都会在运行时产生 NRE(空引用异常)。在 LINQ to Entities 中,它被转换并执行为 SQL。 SQL 对 subASSRED.SomeProperty
这样的表达式没有问题,因为 SQL 自然支持 NULL
,即使 SomeProperty
通常不允许 NULL
。因此 SQL 查询正常执行,但现在 EF 必须将结果具体化为对象,而 C# 对象 属性 是 not 可为空的,因此出现了有问题的错误。
要解决它,请找到 int
属性(es) 并在查询中使用以下模式:
SomeIntProperty = (int?)subASSRED.SomeIntProperty ?? 0 // or other meaningful default
或将接收对象 属性 类型更改为 int?
并保持原始查询不变。
对任何不可为 null 的类型执行相同的操作 属性,例如DateTime
、double
、decimal
、Guid
等