在从不同列表进行查询时,未将对象引用设置为对象的实例

本文关键字:对象引用 设置 实例 对象 列表 查询 | 更新日期: 2023-09-27 18:00:39

我有下面的linq。由于我从两个数据上下文中进行查询,所以我将这些表分解为var列表。但是,我出现了错误"Object reference not set to a instance of a Object"。发生这种情况是因为edr为null。

var meetingsQuery = (from s in this.ModelContext.Meetings select s).ToList(); 
var deliverablesQuery = (from s in this.ModelContext.Deliverables select s).ToList(); 
var deliverableDatesQuery = (from s in this.ModelContext.DeliverableDates select s).ToList();
var refDateTypesQuery = (from s in this.ModelContext.RefDateTypes select s).ToList(); 
var refDeliverablesQuery = (from s in this.ModelContext.RefDeliverables select s).ToList();
var updatesQuery = (from s in this.ArenaUpdateBASEModelContext.Updates select s).ToList(); 
var updateQCsQuery = (from s in this.ArenaUpdateBASEModelContext.UpdateQCs select s).ToList();
var submissionUpdates = (from e in meetingsQuery 
                         from edr in deliverablesQuery.Where(dr => dr.MeetingId == e.MeetingId && !dr.DeletedFlag).DefaultIfEmpty()
                                 from ed in deliverableDatesQuery.Where(d => d.DeliverableId == edr.DeliverableId && !d.DeletedFlag && d.RefDateTypeId == 1).DefaultIfEmpty()
                                 from ed2 in deliverableDatesQuery.Where(d2 => d2.DeliverableId == edr.DeliverableId && !d2.DeletedFlag && d2.RefDateTypeId == 2).DefaultIfEmpty()
                                 join ret in refDateTypesQuery on ed.RefDateTypeId equals ret.RefDateTypeId
                                 join rdt in refDeliverablesQuery on edr.RefDeliverableId equals rdt.RefDeliverableId
                                 join upd in updatesQuery on edr.RefDsgnSubmissionTypeId equals upd.UpdateId
                                 join uqc in updateQCsQuery on upd.UpdateId equals uqc.UpdateId
                                 where
                                        !e.DeletedFlag && !ret.DeletedFlag && !rdt.DeletedFlag && !upd.DeletedFlag && !uqc.DeletedFlag && e.ProjectId == arenaPiD// && rdt. .ObjectIdLink == "Update_UpdateId"
                                        && uqc.RefQCId == 6  // Distributed
                                        && uqc.RefQCStatusId == 2 // Complete
                                 orderby e.ScheduledDT descending
                                 select new
                                 {
                                     e.MeetingId,
                                     e.ScheduledDT,
                                     edr.DeliverableId,
                                     edr.RefDeliverableId,
                                     rdt.DeliverableAbbrv,
                                     UpdateId = edr.RefDsgnSubmissionTypeId != null ? edr.RefDsgnSubmissionTypeId : 0,
                                     RefRecommendationId = upd.RefRecommendationId != null ? upd.RefRecommendationId : 0,
                                     uqc.RefQCId,
                                     uqc.RefQCStatusId,
                                     DeadlineDate = ed != null ? ed.DeliverableDateValue.ToString() : "",
                                     ActualDate = ed2 != null ? ed2.DeliverableDateValue.ToString() : ""
                                 }).ToList();

在从不同列表进行查询时,未将对象引用设置为对象的实例

DefaultIfEmpty在Linq-to对象和Linq-to SQL中的工作方式有很大的不同,这与两者处理null的方式不同有关。

在SQL中,来自LEFT OUTER JOIN的空记录填充有null值。由于SQL从不引用记录本身,所以这不是问题。为不匹配的edr写入edr.DeliverableId时,结果为null。

Linq与SQL不同。当您试图引用不匹配的edr的任何字段或属性时,所产生的错误正是您所看到的。在DefaultIfEmpty调用之后对edr的每次引用都需要首先检查edr是否有效。

然而,除了眼前的错误。。。

您在该查询中混合了两种联接形式(内部和外部),结果令人费解且出乎意料。使用DefaulIfEmpty进行外部联接时遇到的问题会被后续的内部联接所否定,该内部联接取决于外部联接。这意味着你正在经历所有的痛苦和折磨,却没有任何回报。

此连接块:

    join ret in refDateTypesQuery on ed.RefDateTypeId equals ret.RefDateTypeId
    join rdt in refDeliverablesQuery on edr.RefDeliverableId equals rdt.RefDeliverableId
    join upd in updatesQuery on edr.RefDsgnSubmissionTypeId equals upd.UpdateId
    join uqc in updateQCsQuery on upd.UpdateId equals uqc.UpdateId

其中的每一个最终都取决于edr的外部联接,从而产生一个输出,即使你花时间计算出外部联接的副作用,也会抵消DefaultIfEmpty的影响。

你需要重新思考你的逻辑。

我建议将这个问题分解为一系列中间查询。一步一步构建查询,在最后阶段连接结果。

例如,您将ed作为外部联接,然后对其进行与rdt的内部联接,并通过where子句中rdt的属性进行进一步筛选。把所有这些都刮出来,放在一个中间,然后再加入它。对edt执行同样的操作:创建连接零件的中间体。将结果展平,以便在最终查询中使用。


顺便说一句,您不一定需要将所有这些数据都带到内存中。即使您的数据在不同的物理服务器上,您通常仍然可以让Linq到SQL与它们对话。例如,当您以SQL Server为目标时,可以为Table属性指定一个3部分或4部分的名称,以访问同一服务器上的其他数据库或链接服务器上的数据库中的数据。可能有用。