繁体   English   中英

如何在Linq中执行左外连接

[英]How to perform left outer join in Linq

我有3个表,包含以下数据和结构:

Modules

Id          Modulename
----------------------
1           Corp
2           Local
3           Medium

RuleChange

Id      CanDrop     CanLoad     SensorId
----------------------------------------
10      yes         No          113
11      Yes         No          113
12      No          Yes         113
12      No          Yes         114

Rules

Id      Message     ModuleId
----------------------------
10      Xyz         1
11      CVV         0
12      RTV         2
13      LBL         2

我需要在3个表RulesModulesRuleChange和where子句上执行左外连接

任务:列出所有规则及其RuleChange数据和模块名称。

SensorId = 113

预期产量:

Id      Message     Modulename      CanLoad     CanDrop
-------------------------------------------------------
10      Xyz          Corp               Yes      No
11      CVV          Null               No       Yes     
12      RTV          Local              Yes      No
13      LBL          Local              Null     Null

我尝试了什么:

var query = from sr in _context.Rules
            join m in (
                       (from md in _context.Modules
                        select new { md.Id, md.ModuleName })) on sr.ModuleId equals m.Id into moduleRule
                        from m in moduleRule.DefaultIfEmpty()
                        join t in (
                            (from e in _context.RuleChanges
                             where
         e.SensorId == sensorId
                             select new
                             {
                                 e.Sid,
                                 e.CanLoad,
                                 e.Drop
                             })) on sr.Sid equals t.Sid into RuleDiff
                        from t in RuleDiff.DefaultIfEmpty()
                        select new
                        {
                            sr.Sid,
                            sr.Message,
                            CanLoad = t.CanLoad,
                            Drop = t.Drop,
                            sr.ModuleId,
                            ModuleName = m.ModuleName
                        };

var result = query.ToList();

但是,我收到此错误:

NullReferenceException:对象引用未设置为对象的实例..

我认为这是由于连接操作中的空键...但我没有弄清楚该键。

我注意到EF生成了一个SQL查询,它可以产生所需的输出:

SELECT 
    [t].[Id], [t].[ModuleName], 
    [t0].[Sid], [t0].[CanLoad], [t0].[Drop], 
    [sr].[Sid] AS [Sid0], [sr].[Message], [sr].[ModuleId]
FROM
    [SuricataRules] AS [sr]
LEFT JOIN 
    (SELECT 
         [md].[Id], [md].[ModuleName]
     FROM 
         [Modules] AS [md]) AS [t] ON [sr].[ModuleId] = [t].[Id]
LEFT JOIN 
    (SELECT 
         [e].[Sid], [e].[CanLoad], [e].[Drop]
     FROM 
         [RuleChanges] AS [e]
     WHERE 
         [e].[SensorId] = @__sensorId_0) AS [t0] ON [sr].[Sid] = [t0].[Sid]

在这种情况下,访问CanLoad属性CanLoad = t.CanLoad,会导致NullReferenceException异常。 所以使用null-conditional运算符来检查它:

select new
{
    sr.Sid,
    sr.Message,
    CanLoad = t?.CanLoad,
    Drop = t?.Drop,
    sr.ModuleId,
    ModuleName = m?.ModuleName
};

使用方法语法

rules
    .GroupJoin(modules, _ => _.ModuleId, _ => _.Id, (r, ms) => new { r, ms })
    .SelectMany(_ => _.ms.DefaultIfEmpty().Select(m => new { _.r, m }))
    .GroupJoin(ruleChanges, _ => _.r.Id, _ => _.Id, (rm, rc) => new { rm, rc })
    .SelectMany(_ => _.rc.DefaultIfEmpty().Select(rc => new {_.rm, rc}))
    .Select(_ => new 
    { 
        Id = _.rm.r.Id, 
        Message = _.rm.r.Message, 
        Modulename = _.rm.m?.Modulename, 
        CanLoad = _.rc?.CanLoad, 
        CanDrop = _.rc?.CanDrop
    });

你能用SQL编写查询吗?

我也对linq感到困惑所以当事情变得太复杂时我会这样做!

我将在sql中编写/测试我的查询,然后使用实体框架将查询粘贴到“Database.SQLQuery”方法中。 您可以根据需要修改以下代码段。 在这种情况下,我只返回int List中的IDClient

            using (var _context = new DB.Entities())
            {
                var IDClients = _context.Database.SqlQuery<int>("select distinct idclient FROM dbo.ReportClient LEFT OUTER JOIN dbo.ReportClientDocument ON dbo.ReportClient.IDClient = dbo.ReportClientDocument.IDClient");
                foreach (var IDClient in IDClients)
                {
                    // process the row here
                }
            }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM