使用LinqToSQL生成FULL JOIN

时间:2009-09-14 13:59:35

标签: linq-to-sql outer-join

我有这个linq查询:

(from  rapportBase in New_RapportReferencementBases
join rapportExtensionAll in New_RapportReferencementExtensionBases on rapportBase.New_RapportReferencementId equals rapportExtensionAll.New_RapportReferencementId into jointureRapportExtension
from rapportExtension in jointureRapportExtension.DefaultIfEmpty()

join packExtensionAll in New_PackExtensionBases on rapportExtension.New_PackId equals packExtensionAll.New_PackId into jointurePackExtension
from packExtension in jointurePackExtension.DefaultIfEmpty()
join packBaseAll in New_PackBases on packExtension.New_PackId equals packBaseAll.New_PackId into jointurePackBase
from packBase in jointurePackBase.DefaultIfEmpty()

join domaineBaseAll in New_DomaineBases on packExtension.New_DomaineId equals domaineBaseAll.New_DomaineId into jointureDomaineBase
from domaineBase in jointureDomaineBase.DefaultIfEmpty()
join domaineExtensionAll in New_DomaineExtensionBases on domaineBase.New_DomaineId equals domaineExtensionAll.New_DomaineId into jointureDomaineExtension
from domaineExtension in jointureDomaineExtension.DefaultIfEmpty()  

join compteBaseAll in AccountBases on domaineExtension.New_AccountId equals compteBaseAll.AccountId into jointureCompteBase
from compteBase in jointureCompteBase.DefaultIfEmpty()
join compteExtensionAll in AccountExtensionBases on compteBase.AccountId equals compteExtensionAll.AccountId into jointureCompteExtension
from compteExtension in jointureCompteExtension.DefaultIfEmpty()   
select rapportBase)

生成:

SELECT [t0].[New_RapportReferencementId], [t0].[CreatedOn], [t0].[CreatedBy], [t0].[ModifiedOn], [t0].[ModifiedBy], [t0].[OwningUser], [t0].[OwningBusinessUnit], [t0].[statecode] AS [Statecode], [t0].[statuscode] AS [Statuscode], [t0].[DeletionStateCode], [t0].[VersionNumber], [t0].[ImportSequenceNumber], [t0].[OverriddenCreatedOn], [t0].[TimeZoneRuleVersionNumber], [t0].[UTCConversionTimeZoneCode]
FROM [New_RapportReferencementBase] AS [t0]
LEFT OUTER JOIN [New_RapportReferencementExtensionBase] AS [t1] ON [t0].[New_RapportReferencementId] = [t1].[New_RapportReferencementId]
LEFT OUTER JOIN [New_PackExtensionBase] AS [t2] ON [t1].[New_PackId] = ([t2].[New_PackId])
LEFT OUTER JOIN [New_PackBase] AS [t3] ON [t2].[New_PackId] = [t3].[New_PackId]
LEFT OUTER JOIN [New_DomaineBase] AS [t4] ON [t2].[New_DomaineId] = ([t4].[New_DomaineId])
LEFT OUTER JOIN [New_DomaineExtensionBase] AS [t5] ON [t4].[New_DomaineId] = [t5].[New_DomaineId]
LEFT OUTER JOIN [AccountBase] AS [t6] ON [t5].[New_AccountId] = ([t6].[AccountId])
LEFT OUTER JOIN [AccountExtensionBase] AS [t7] ON [t6].[AccountId] = [t7].[AccountId]

但我想生成:

SELECT [t0].[New_RapportReferencementId], [t0].[CreatedOn], [t0].[CreatedBy], [t0].[ModifiedOn], [t0].[ModifiedBy], [t0].[OwningUser], [t0].[OwningBusinessUnit], [t0].[statecode] AS [Statecode], [t0].[statuscode] AS [Statuscode], [t0].[DeletionStateCode], [t0].[VersionNumber], [t0].[ImportSequenceNumber], [t0].[OverriddenCreatedOn], [t0].[TimeZoneRuleVersionNumber], [t0].[UTCConversionTimeZoneCode]
FROM [New_RapportReferencementBase] AS [t0]
FULL OUTER JOIN [New_RapportReferencementExtensionBase] AS [t1] ON [t0].[New_RapportReferencementId] = [t1].[New_RapportReferencementId]
FULL OUTER JOIN [New_PackExtensionBase] AS [t2] ON [t1].[New_PackId] = ([t2].[New_PackId])
FULL OUTER JOIN [New_PackBase] AS [t3] ON [t2].[New_PackId] = [t3].[New_PackId]
FULL OUTER JOIN [New_DomaineBase] AS [t4] ON [t2].[New_DomaineId] = ([t4].[New_DomaineId])
FULL OUTER JOIN [New_DomaineExtensionBase] AS [t5] ON [t4].[New_DomaineId] = [t5].[New_DomaineId]
FULL OUTER JOIN [AccountBase] AS [t6] ON [t5].[New_AccountId] = ([t6].[AccountId])
FULL OUTER JOIN [AccountExtensionBase] AS [t7] ON [t6].[AccountId] = [t7].[AccountId]

换句话说,我想为这个查询生成完全外连接,而不是只留下。

有人知道如何以简单的方式做到这一点吗?

感谢

3 个答案:

答案 0 :(得分:1)

Linq没有完全外部加入。你必须做两个左连接并将它们连接起来。这是一些看起来像linq的伪代码:

var foj =
    (from l in left
    join r in right on l.Id equals r.Id into g
    from r in g.DefaultIfEmpty()
    select new { l, r })
    .Concat
    (from r in right
    join l in left on r.Id equals l.Id into g
    from l in g.DefaultIfEmpty()
    where l == null
    select new { l, r });

如果您计划将Linq用于Sql,可能最好将此逻辑推送到存储过程。

答案 1 :(得分:0)

请参阅VB团队的这篇文章:

http://blogs.msdn.com/vbteam/archive/2008/02/12/converting-sql-to-linq-part-9-full-outer-join-bill-horst.aspx

看起来有点冗长。

否则,可能有一种方法可以使用Foreign Keys和Union运算符实现您想要的效果。

答案 2 :(得分:0)

可悲的是我之前看过,但我想确定。

我们做的是在存储过程中执行它并通过linqtosql方法访问它。

然后我们像linqtosql一样映射表结果,使用分组来获取链接到另一个实体的集合。

例如,如果我们有一个帐户,其中一些联系人链接到它。我们要求所有联系人为他们每个人提供一个完整的加入帐户和他们的帐户ID组,以获取每个帐户的联系人列表。

它工作得很好但是如果linqtosql能够生成完全连接会更好....