我有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个表Rules
,Modules
,RuleChange
以及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]
答案 0 :(得分:3)
在这种情况下,CanLoad
属性CanLoad = t.CanLoad,
的访问会导致NullReferenceException
异常。因此,请使用null-conditional operator进行检查:
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
});
答案 1 :(得分:0)
你能用SQL编写查询吗?
我也对linq感到困惑所以当事情变得太复杂时我会这样做!
我将在sql中编写/测试我的查询,然后使用实体框架将查询粘贴到“Database.SQLQuery”方法中。您可以根据需要修改以下代码段。在这种情况下,我只返回 int 列表
中的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
}
}