将sql join脚本转换为lambda或linq

时间:2018-06-25 08:27:12

标签: sql linq lambda

我如何将该脚本转换为lambda或linq?

 select a.PayoutID,b.PayoutName 
   from [dbo].[PayoutsOfUser] a 
  inner join [dbo].[Payout] b on a.PayoutID = b.PayoutID
  inner join [dbo].[Users] c on a.UserID = c.UserID 
  where c.UserID = 16

2 个答案:

答案 0 :(得分:0)

var result= PayoutsOfUser.Join(Payout,
              a=>a.PayoutID,
              b=>b.PayoutID,
              (a,b)=>new{PayoutsOfUser=a,Payout=b})
            .Join(Users,
              a=>a.PayoutsOfUser.UserID,
              c=>c.UserID,
              (a,c)=>new{a.PayoutsOfUser,a.Payout,Users=c})
            .Where(x=>x.Users.UserID==16)
            .Select(x=>new
            {
                 a.PayoutID,
                 b.PayoutName
            }).ToList();

答案 1 :(得分:0)

方法语法(=带lambda表达式的语法)比查询语法具有更多功能。因此,我更喜欢在查询语法之上使用方法语法。

但是有一个例外:当连接三个或更多表时,该方法的语法看起来很可怕,就像Sebu在他的回答中所示。 this answer where the two methods for joining three tables are compared

中也显示

pst_n=fiona.open(r'C:\Users\user\Desktop\new\PST')#new pst pst_o=fiona.open(r'C:\Users\user\Desktop\old\PST')#old_pst pst_n.schema d1 = pst_n.schema['properties'] d2 = pst_o.schema['properties'] d1_items = set(d1.items()) d2_items = set(d2.items()) result = sorted([(k, 'd1', v) for k, v in d1_items if (k, v) not in d2_items] + [(k, 'd2', v) for k, v in d2_items if (k, v) not in d1_items]) result = [(k, v, d) for k, d, v in result] pprint(result) 的内部表达式是相同的,无论您使用的是方法语法还是查询语法,因此生成的SQL语句差别不会很大。

因此,我的建议是:尽可能使用方法语法,但是为了提高可读性,减少错误,提高可维护性:使用查询语法连接三个表。

如果必须经常进行三个表的联接,请考虑创建一个扩展函数来隐藏联接的完成方式:

请参阅:extension functions demystified

以下函数采用三个输入序列:IQueryable,IQueryable和IQueryable。
它在使用T1Join1Selector和T2Join1Selector提取的键上连接前两个序列,
如果将使用T2Join2Selector和T3Join2Selector进行运算的键上的后两个序列结合在一起
从每个匹配的T1 / T2 / T3,它根据resultSelector创建一个结果

[('ADDRESS', 'int:4', 'd1'),
 ('ADDRESS', 'str:254', 'd2'),
 ('AREA', 'float:19.11', 'd2'),
 ('DEC_ID', 'int:4', 'd1'),
 ('DEC_ID', 'str:254', 'd2'),
 ('DESC_', 'str:254', 'd1'),
 ('FID_PERIVL', 'int:9', 'd1'),
 ('KAEK', 'str:50', 'd1'),
 ('KAEK', 'str:12', 'd2'),
 ('LEN', 'float:19.11', 'd2'),

或者使用查询语法连接三个表:

IQueryable

用法类似于使用方法语法联接两个表的方式:

public static IQueryable<TResult> Join<T1, T2, T3, 
    TKeyJoin1, TKeyJoin2, TResult>(
        this IQueryable<T1> table1,
        IQueryable<T2> table2,
        IQueryable<T3> table3,
        Expression<Func<T1, TKeyJoin1>> table1Join1KeySelector,
        Expression<Func<T2, TKeyJoin1>> table2Join1KeySelector,
        Expression<Func<T2, TKeyJoin2>> table2Join2KeySelector,
        Expression<Func<T3, TKeyJoin2>> table3Join2KeySelector,
        Expression<Func<T1, T2, T3, Tresult>> resultSelector)
{
     return Tabl1.Join(table2,           // join table1 and table2
     t1 => table1Join1KeySelector(t1),   // select the key from table1 for the first join
     t2 => table2Join1KeySelector(t2),   // select the key from table2 for the first join
     (t1, t2) => new                     // remember the matching records as T1 and T2
     {
          T1 = t1,
          T2 = t2,
     })

     // use this as input for the second join:
     .Join(table3,
     // use the T2 in the result of the first join as key for the second join 
     joinedT1andT2 => table2Join2KeySelector(joinedT1andT2.T2),
     t3 => table3Join2KeySelector(t3),    // select the key from table3 for the 2nd join

     // and use the result of the first and second join to create a linq-result:
     (joinedT1andT2, t3) => resultSelector(joinedT1andT2.T1, joinedT1andT2.T2, T3);
}
  

我看到您的第二个联接位于a和c上,而我的第二个联接位于b和c上。我确定您会知道如何根据需要重写代码

由于此函数的结果是一个IQueryable,因此该函数将仅更改表达式。查询尚未执行。因此,您可以安全地将其与其他IQueryable函数混合使用:

public static IQueryable<TResult> Join<T1, T2, T3, 
    TKeyJoin1, TKeyJoin2, TResult>(
        this IQueryable<T1> table1,
        IQueryable<T2> table2,
        IQueryable<T3> table3,
        Expression<Func<T1, TKeyJoin1>> table1Join1KeySelector,
        Expression<Func<T2, TKeyJoin1>> table2Join1KeySelector,
        Expression<Func<T2, TKeyJoin2>> table2Join2KeySelector,
        Expression<Func<T3, TKeyJoin2>> table3Join2KeySelector,
        Expression<Func<T1, T2, T3, Tresult>> resultSelector)
{
    return select resultSelector(table1, table2, table3) 
    from table1 
    join table2 on table1Join1KeySelector(table1) == table2Join1KeySelector(table2)
    join table3 on table2Join2KeySelector(table2) == table3Join2KeySelector(table3) 
}

在执行不返回var result = a.Join(b, c, // join your tables a, b, c t1 => t1.PayoutId, // first join on a.PayoutID = b.PayoutID t2 => t2.PayoutId, t2 => t2.UserId, // second join on b.UserID = c.UserID t3 => t3.UserId, (t1, t2, t3) => new // from the matching records create one new object { PayoutId = t1.PayoutId, PayoutName = t2.PayoutName, ... }); 的操作之前,查询仍不会执行,例如var resultQuery = a.Where(t1 => t1.Name = ...) .Join( /* 3-table join as described above */ ) .GroupBy(joinResult => ...) .Take(4); / IQueryable / ToList / ...