如何使用 Linq 检索 table1 中的所有列和 table2 中的匹配列(左外连接)

How to retrieve all columns from table1 and matching columns from table2(Left outer join) using Linq

我必须检索表 1 中的所有列和表 2 中的匹配列。我有一个存储过程:

alter  Procedure [dbo].[usp_Property]
@UserId bigint =null
As
Begin
select P.PID, P.PropertyName, P.SBUArea, P.ListedOn, 
       P.Availability, P.Price,   F.UserID, F.PID as FavProjId  
       from dbo.Property P left outer join dbo.Favorite F
       on (F.PID=P.PID And F.UserID=@UserId)

我想获取相同的 Linq 查询。到目前为止,我尝试过

//User Id comes from session..
//var userId
var result=(from p in Properties
                   join f in Favorites
                   on p.PID equals f.PID into r
                   from r1 in r.DefaultIfEmpty()
                   where r1.UserID==userId
                   select new
                   {
                     p.PID,
                      p.PropertyName,                       
                      p.SBUArea, p.ListedOn,
                      r1.UserId
                   });

谁能指正一下。我想在这里使用左外连接或任何其他替代方法。

如果将 where 子句放在 join 之后,您可能会得到空引用异常,因为 DefaultIfEmpty returns 不匹配行的默认值。您可以像这样在加入之前过滤记录:-

var result=(from p in Properties
            join f in Favorites.Where(x => x.UserID == userId)
            on p.PID equals f.PID into r
            from r1 in r.DefaultIfEmpty()
            select new
            {
                p.PID,
                p.PropertyName,                       
                p.SBUArea, 
                p.ListedOn,
                r1.UserId
            });

请注意,您需要使用 r1 访问 Favorites 的属性。

更新:

据我了解,您需要 Property table 中的所有记录并且仅匹配 Favorite table 中的行。但是您在收藏夹 table 上有一个过滤器,因此最终数据源会有所不同。让我通过这个例子阐明我的观点:-

假设您在 Property table 中有以下数据:-

PID    PropertyName    Availability    Price
 1          aaa            true         20
 2          bbb            false        10
 3          ccc            true         50
 4          ddd            false        80
 5          eee            true         55
 6          fff            false        70

Favorite table像这样:-

FID    PID    UserId
 1      4      1001
 2      2      1005
 3      5      1007

假设您想要 UserId 1005 的所有记录,那么即使 UserId 1005 与 [=45= 不匹配,结果也应该包含从 1 到 6 的所有 属性 ID ] Id 是 4 和 2 对吗?所以上面的查询是按照这种理解。使用相同的示例和输出检查此 Fiddle

在您的选择中使用匿名对象

var result = from t in table1
             join x in table2
             on t.id equals x.id
             select new { id = t.id, col1 = t.col1, col2 = x.col2 }

如果我美化你的 SP 代码,我得到这个:

DECLARE @UserId int 
SET @UserId = 12435 

SELECT 
     P.PID
    ,P.PropertyName
    ,P.SBUArea
    ,P.ListedOn 
    ,P.Availability
    ,P.Price
    ,F.UserID
    ,F.PID AS FavProjId  
FROM Property AS P 
LEFT JOIN Favorite AS F
    ON (F.PID=P.PID AND F.UserID = @UserId)

现在我想知道您是否需要 SQL 的 WHERE 子句中的 UserId,或者是否确实需要在联接中。

但是无论如何,这里的 LINQ 等价物正好是 SQL:

System.Int64 __UserId = 12435;

var query = (
    from P in Repo.Property
    from F in Repo.Favorite
         .Where(fav=> fav.PID == P.PID && fav.UserID == __UserId)
         .DefaultIfEmpty() // <== makes join left join
    select new
    {
         PID = P.PID
        ,PropertyName = P.PropertyName
        ,SBUArea = P.SBUArea
        ,ListenOn = P.ListedOn 
        ,Availabiity = P.Availability
        ,Price = P.Price
        ,UserId = F.UserID
        ,FavProjId = F.PID 
    }

);

var data = (query).ToList();