LINQ TO SQL 中的join

      join对于喜欢写SQL的朋友来说还是比较实用,也比较容易接受的东西。在LINQ TO SQL中,写多表查询,同样可以写join,只是它有它自己的语法要求而已,语义都是一样的,下面我来讲下LINQ TO SQL中的join最基本的形式:都是最简单的,当然还有其它方面的内容,如:怎样加上过滤条件,如何分组,如何排序等等,为了单纯说join的用法,这里就简化下。

from c  in  Customers
join p 
in  Purchases on c.ID equals p.CustomerID
select c.Name 
+   "  bought a  "   +  p.Description


      生成的SQL:

SELECT ([t0].[Name]  +  @p0)  +  [t1].[Description] AS [value]
FROM [Customer] AS [t0]
INNER JOIN [Purchase] AS [t1] ON ([t0].[ID]) 
=  [t1].[CustomerID]

 

     通过生成的SQL,我们可以非常清晰的看出,显示的使用了inner join,它的基本要求好下:
         1:包含join和on关键字,如果只有join没有on,会报语法错误。

         2:外键关联时,用的是关键字equals,而不能像SQL一样用等号。

         3:必须显示调用要显示的字段。即要出现select 字段,否则会报错。

      LINQ TO SQL与传统SQL的相同点:

        1:join的用法,并不关心主表在前还是在后,最终的结果都是相同的。上面的查询我们也可以这样写。

from p  in  Purchases
    join c 
in  Customers on p.CustomerID equals c.ID
    select c.Name 
+   "  bought a  "   +  p.Description;

        2:LINQ TO SQL同样支持两表以上的关联,

from c  in  Customers
join p 
in  Purchases on c.ID equals p.CustomerID            //  first join
join pi  in  PurchaseItems on p.ID equals pi.PurchaseID      //  second join
select  new
ExpandedBlockStart.gifContractedBlock.gif
{
    c.Name, p.Description, pi.Detail
}

 

     LINQ TO SQL与传统SQL的不同点:

       1:LINQ TO SQL中的join,如果带有into,可以提前对表进行过滤条件的操作,而不用等到两表进行迪卡尔积产生虚似表后再进行join on的条件过滤。

ContractedBlock.gif ExpandedBlockStart.gif Code
from c in Customers
join p 
in Purchases.Where (p2 => p2.Price > 1000)
    on c.ID equals p.CustomerID
into custPurchases
where custPurchases.Any()
select 
new
{
    CustName 
= c.Name,
    custPurchases
}

       产生的SQL:

ContractedBlock.gif ExpandedBlockStart.gif Code
SELECT [t0].[Name] AS [CustName], [t1].[ID], [t1].[CustomerID], [t1].[Date], [t1].[Description], [t1].[Price], (
    SELECT COUNT(
*)
    FROM [Purchase] AS [t3]
    WHERE (([t0].[ID]) 
= [t3].[CustomerID]) AND ([t3].[Price] > @p0)
    ) AS [value]
FROM [Customer] AS [t0]
LEFT OUTER JOIN [Purchase] AS [t1] ON (([t0].[ID]) 
= [t1].[CustomerID]) AND ([t1].[Price] > @p0)
WHERE EXISTS(
    SELECT NULL AS [EMPTY]
    FROM [Purchase] AS [t2]
    WHERE (([t0].[ID]) 
= [t2].[CustomerID]) AND ([t2].[Price] > @p0)
    )
ORDER BY [t0].[ID], [t1].[ID]

  

      2:LINQ TO SQL包含一个groupjoin的概念,来看下MSDN对它的定义:

           Queryable..::.GroupJoin 方法:基于键相等对两个序列的元素进行关联并对结果进行分组。这样情况一般都发生在一对多的情况,以主表的主键为分组对象,通过主表的主键来查询出子表的集合。

           拿客人和消费记录表来说吧:一个客人会有多笔消费,我们要想得到所有客人的所有消费情况及客人姓名,即最外层的集合对象是所有客人信息,而客人的消费信息通过一个EntitySet集合来体现。在传统SQL中要想通过一个查询是做不到的,因为传统的SQL返回的只是一个具体的集合,具体记录中是不能再包含子记录的。而LINQ TO SQL则可以做到,可以通过主表记录的EntitySet属性来包含子表的集合。

var list =     (from c in db.Customers
join p in db.Purchases on c.ID equals p.CustomerID
into custPurchases
select new
{custPurchases,c.Name}).ToList ();

 

             效果图:如图一,

           可以非常清楚的看出子表Puchase的内容以集合Puchase出现在最终的结果中,另外一列的内容是客户名。我们可以非常方便的取用户的某些信息。

// 第一个用户的所有消费记录
            List < Purchase >  _list  =  list[ 0 ].custPurchases .ToList < Purchase  > () ;
            
// 取第一个用户的第一条消费记录的价格
             decimal  dPrice  =  _list[ 0 ].Price;


           可以看出LINQ模式对于开发效率还是有很大程度提高的,完全面向对象,逻辑性好,阅读性强。

           对应的SQL:

SELECT [t1].[ID], [t1].[CustomerID], [t1].[Date], [t1].[Description], [t1].[Price], (
    SELECT COUNT(
* )
    FROM [Purchase] AS [t2]
    WHERE ([t0].[ID]) 
=  [t2].[CustomerID]
    ) AS [value], [t0].[Name]
FROM [Customer] AS [t0]
LEFT OUTER JOIN [Purchase] AS [t1] ON ([t0].[ID]) 
=  [t1].[CustomerID]
ORDER BY [t0].[ID], [t1].[ID]

 

           效果图:如图二,传统SQL看起来是一个完整的集合,它没有子对象的概念。

 

         总结:上面的所有语句都可以用等效的拉姆达表态式来代替,只不过如果是像我一样的初学者,总觉的看拉姆达表达示特别别扭,用类似SQL的语句会容易接受些。join可以和上篇文章讲的selectMany来相互转换。要想join生成LEFT OUT JOIN,同样可以用DefaultIfEmpty()来实现,有兴趣的朋友可以试下。


注:
   文中参考nutshell示例

 

 

 

转载于:https://www.cnblogs.com/ASPNET2008/archive/2008/12/21/1358152.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值