我寫執行左邊LINQ加入的方法,採用標準GroupJoin
/SelectMany
/DefaultIfEmpty
方法:額外子查詢加入
public static IQueryable<TResult> LeftJoin<TLeft, TRight, TKey, TResult>(
this IQueryable<TLeft> left,
IEnumerable<TRight> right,
Expression<Func<TLeft, TKey>> leftKeySelector,
Expression<Func<TRight, TKey>> rightKeySelector,
Expression<Func<TLeft, TRight, TResult>> resultSelector)
{
var paramL = Expression.Parameter(typeof(TLeft), "l");
var paramR = Expression.Parameter(typeof(TRight), "r");
var paramRs = Expression.Parameter(typeof(IEnumerable<TRight>), "rs");
var expr = Expression.Lambda<Func<TLeft, IEnumerable<TRight>, IEnumerable<TResult>>>(
Expression.Call(
typeof(Enumerable),
"Select",
new [] { typeof(TRight), typeof(TResult) },
Expression.Call(typeof(Enumerable), "DefaultIfEmpty", new[] { typeof(TRight) }, paramRs),
Expression.Lambda<Func<TRight, TResult>>(
Expression.Invoke(resultSelector, paramL, paramR),
paramR)),
paramL,
paramRs
);
return left
.GroupJoin(
right,
leftKeySelector,
rightKeySelector,
expr)
.SelectMany(x => x);
}
我測試從而:
var q = myDB.PurchaseOrderHeaders
.LeftJoin(
myDB.PurchaseOrderLines,
po => po.PurchaseOrderGUID,
line => line.PurchaseOrderGUID,
(po, line) => new { PO = po, Line = line }
);
var e = q.AsEnumerable();
我期望這樣的SQL:
SELECT [t0].[PurchaseOrderGUID], ..., [t1].[PurchaseOrderLineGUID], ...
FROM [dbo].[PurchaseOrderHeader] AS [t0]
LEFT OUTER JOIN [dbo].[PurchaseOrderLine] AS [t1]
ON [t0].[PurchaseOrderGUID] = [t1].[PurchaseOrderGUID]
但是得到了這個:
SELECT [t0].[PurchaseOrderGUID], ..., [t2].[test], [t2].[PurchaseOrderLineGUID], ...
FROM [dbo].[PurchaseOrderHeader] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[PurchaseOrderLineGUID], ...
FROM [dbo].[PurchaseOrderLine] AS [t1]
) AS [t2] ON [t0].[PurchaseOrderGUID] = [t2].[PurchaseOrderGUID]
區別在於子查詢與SELECT 1 as [test]
。它爲什麼產生這個?它是否可能對性能有重大影響?如果是這樣,我可以修改查詢來消除它嗎?