Linq的左外联接 - 如何逼迫

时间:2010-03-25 16:52:49

标签: sql linq linq-to-sql tsql

我在LINQ中有一个LEFT OUTER OUTER连接,它与外部连接条件相结合,但没有提供所需的结果。这种组合基本上限制了我的左侧结果。这是LINQ和结果SQL。我想要的是LINQ查询中的“AND([t2]。[EligEnd] = @ p0”不是连接条件的一部分,而是在连接之前过滤结果的子查询。

提前致谢(从LINQPad取样) - 道格

(from l in Users
                       join mr in (from mri in vwMETRemotes where met.EligEnd == Convert.ToDateTime("2009-10-31") select mri) on l.Mahcpid equals mr.Mahcpid into lo
                       from g in lo.DefaultIfEmpty()
                       orderby l.LastName, l.FirstName
                       where l.LastName.StartsWith("smith") && l.DeletedDate == null 
                       select g)

以下是生成的SQL

-- Region Parameters
DECLARE @p0 DateTime = '2009-10-31 00:00:00.000'
DECLARE @p1 NVarChar(6) = 'smith%'
-- EndRegion
SELECT [t2].[test], [t2].[MAHCPID] AS [Mahcpid], [t2].[FirstName], [t2].[LastName], [t2].[Gender], [t2].[Address1], [t2].[Address2], [t2].[City], [t2].[State] AS [State], [t2].[ZipCode], [t2].[Email], [t2].[EligStart], [t2].[EligEnd], [t2].[Dependent], [t2].[DateOfBirth], [t2].[ID], [t2].[MiddleInit], [t2].[Age], [t2].[SSN] AS [Ssn], [t2].[County], [t2].[HomePhone], [t2].[EmpGroupID], [t2].[PopulationIdentifier]
FROM [dbo].[User] AS [t0]
LEFT OUTER JOIN (
    SELECT 1 AS [test], [t1].[MAHCPID], [t1].[FirstName], [t1].[LastName], [t1].[Gender], [t1].[Address1], [t1].[Address2], [t1].[City], [t1].[State], [t1].[ZipCode], [t1].[Email], [t1].[EligStart], [t1].[EligEnd], [t1].[Dependent], [t1].[DateOfBirth], [t1].[ID], [t1].[MiddleInit], [t1].[Age], [t1].[SSN], [t1].[County], [t1].[HomePhone], [t1].[EmpGroupID], [t1].[PopulationIdentifier]
    FROM [dbo].[vwMETRemote] AS [t1]
    ) AS [t2] ON ([t0].[MAHCPID] = [t2].[MAHCPID]) AND ([t2].[EligEnd] = @p0)
WHERE ([t0].[LastName] LIKE @p1) AND ([t0].[DeletedDate] IS NULL)
ORDER BY [t0].[LastName], [t0].[FirstName]

2 个答案:

答案 0 :(得分:1)

我不确定它是否会使用“AND([t2]。[EligEnd] = @ p0”更改结果集作为子查询的一部分而不是连接条件。我喜欢复杂查询的一件事可能会帮助你。我喜欢在组合它们之前将它们分解成较小的查询。延迟执行LINQ让我们通过最终调用数据库来执行多个语句。这样的事情:

var elig = from mri in vwMETRemotes 
           where met.EligEnd == Convert.ToDateTime("2009-10-31") 
           select mri;

var users = from l in Users
            where l.LastName.StartsWith("smith")
            where l.DeletedDate == null

var result = from l in users
             join mr in elig on l.Mahcpid equals mr.Mahcpid into lo
             from g in lo.DefaultIfEmpty()
             orderby l.LastName, l.FirstName
             select g

这样打破它可以使调试变得更容易,也许它可以更好地告诉LINQ你想要什么。

答案 1 :(得分:1)

代码最终看起来像这样。 RecodePopulation和RecordRegistration只是从查询中转换值的方法。

            var elig = from mri in db.MetRemote 
                    where mri.EligEnd == Convert.ToDateTime(ConfigurationManager.AppSettings["EligibilityDate"]) 
                   orderby mri.EligEnd 
                   select mri;

        var users = from l in db.Users
                    where l.LastName.StartsWith(filter)
                    where l.DeletedDate == null
                        select l;

        var results = (from l in users
                     join m in elig on l.MahcpId equals m.MAHCPID into lo
                     from g in lo.DefaultIfEmpty()
                     orderby l.LastName, l.FirstName
                       select new UserManage()
                       {
                           Username = l.Username,
                           FirstName = l.FirstName,
                           LastName = l.LastName,
                           DateOfBirth = l.DOB,
                           Gender = l.Gender,
                           Status = RecodePopulation(g.Population, l.CreatedDate),
                           UserId = l.Id,
                           WellAwardsRegistered = RecodeRegistration(l.Id, 1)

                       }).Distinct().OrderBy(a => a.LastName).ThenBy(n => n.FirstName).Skip((currentPage - 1) * resultsPerPage).Take(resultsPerPage);