LINQ多个左外连接带有“或”子句

时间:2011-06-14 21:36:29

标签: c# linq-to-sql .net-3.5

基本上,我尝试在LINQ中传输此查询。

DECLARE @p1 UniqueIdentifier SET @p1 = 'AC1D85C1-28F1-46A3-9C6A-3B7446609A2A'
DECLARE @p2 UniqueIdentifier SET @p2 = NEWID()
SELECT
    [MTD].[Description],
    [MTD].[MessageTypeID],
    ISNULL([AMT].[ApplicationMessageTypeID], NEWID()),
    ISNULL([AMT].[EventForwardingRuleID], '1001')
FROM [dbo].[MessageType] as [MT]
INNER JOIN [dbo].[MessageTypeDescription] AS [MTD] 
        ON [MT].[MessageTypeID] = [MTD].[MessageTypeID]
LEFT OUTER JOIN [dbo].[ApplicationMessageType] AS [AMT] 
        ON [AMT].[MessageTypeID] = [MT].[MessageTypeID]
        AND ( [AMT].[ApplicationID] = @p1 OR [AMT].[ApplicationID] IS NULL )
WHERE [MTD].[Culture] = 'fr'

我知道大多数情况下查询看起来应该是这样的:

(from mt in db.MessageTypes
join mtd in db.MessageTypeDescriptions
    on mt.MessageTypeID equals mtd.MessageTypeID
join amt in db.ApplicationMessageTypes
    on new { mt.MessageTypeID, (applicationId || null) } equals new { amt.MessageTypeID, amt.ApplicationID }
    into appMessageTypes
from amt in appMessageTypes.DefaultIfEmpty()
where mtd.Culture == culture
select new ApplicationEditEventTypeModel
{
    ApplicationMessageTypeID = amt.ApplicationMessageTypeID == null ? Guid.NewGuid() : amt.ApplicationMessageTypeID,
    Description = mtd.Description,
    MessageTypeID = mtd.MessageTypeID,
    EventForwardingRuleID = amt.EventForwardingRuleID == null ? 0 : amt.EventForwardingRuleID
});

这里我真正不确定的部分是“ApplicationMessageTypes”部分。对于多重左连接查询,我使用new {} equals new {}构造,但在这种情况下,我有2个子句( [AMT].[ApplicationID] = @p1 OR [AMT].[ApplicationID] IS NULL )

我应该使用像new { mt.MessageTypeID, new { applicationId ,null }} equals new { amt.MessageTypeID, amt.ApplicationID }这样的东西吗?这似乎太奇怪了,不可能是真实的。

2 个答案:

答案 0 :(得分:1)

(from mt in db.MessageTypes
join mtd in db.MessageTypeDescriptions
    on mt.MessageTypeID equals mtd.MessageTypeID
from amt in db.ApplicationMessageTypes
    .Where(a => a.MessageTypeID == mt.MessageTypeID &&
          (a.ApplicationID == applicationId || !a.ApplicationID.HasValue)).DefaultIfEmpty()
where mtd.Culture == culture
select new ApplicationEditEventTypeModel
{
    ApplicationMessageTypeID = amt.ApplicationMessageTypeID ?? Guid.NewGuid(),
    Description = mtd.Description,
    MessageTypeID = mtd.MessageTypeID,
    EventForwardingRuleID = amt.EventForwardingRuleID ?? 0
});

答案 1 :(得分:0)

我认为ApplicationId子句看起来并不像JOIN的一部分 - 即它实际上不是外键关系的一部分 - 而是它只是一个正常的WHERE条件。

所以我建议在SQL和LINQ中将ApplicationId移到WHERE

DECLARE @p1 UniqueIdentifier SET @p1 = 'AC1D85C1-28F1-46A3-9C6A-3B7446609A2A'
DECLARE @p2 UniqueIdentifier SET @p2 = NEWID()
SELECT
    [MTD].[Description],
    [MTD].[MessageTypeID],
    ISNULL([AMT].[ApplicationMessageTypeID], NEWID()),
    ISNULL([AMT].[EventForwardingRuleID], '1001')
FROM [dbo].[MessageType] as [MT]
INNER JOIN [dbo].[MessageTypeDescription] AS [MTD] 
        ON [MT].[MessageTypeID] = [MTD].[MessageTypeID]
LEFT OUTER JOIN [dbo].[ApplicationMessageType] AS [AMT] 
        ON [AMT].[MessageTypeID] = [MT].[MessageTypeID]
WHERE [MTD].[Culture] = 'fr'
        AND (AMT IS NULL OR ([AMT].[ApplicationID] = @p1 OR [AMT].[ApplicationID] IS NULL ))

(from mt in db.MessageTypes
join mtd in db.MessageTypeDescriptions
      on mt.MessageTypeID equals mtd.MessageTypeID
join amt in db.ApplicationMessageTypes
      on new mt.MessageTypeID equals amt.MessageTypeID
    into appMessageTypes
from amt in appMessageTypes.DefaultIfEmpty()
where mtd.Culture == culture
      && amt==null || (amt.ApplicationID == null || amt.ApplicationID == applicationId)
select new ApplicationEditEventTypeModel
{
 ApplicationMessageTypeID = amt.ApplicationMessageTypeID == null ? Guid.NewGuid() : amt.ApplicationMessageTypeID,
 Description = mtd.Description,
 MessageTypeID = mtd.MessageTypeID,
 EventForwardingRuleID = amt.EventForwardingRuleID == null ? 0 : amt.EventForwardingRuleID
});

如果你想让ApplicationId子句更接近原始的ApplicationMessageType表,你也可以使用嵌套的select(或视图)