.NET深入实战系列—Linq to Sql进阶
最近在写代码的过程中用到了Linq查询,在查找资料的过程中发现网上的资料千奇百怪,于是自己整理了一些关于Linq中容易让人困惑的地方。
本文全部代码基于:UserInfo与Class两个表,其中Class中的UserId与UserInfo中的Id对应

本文唯一访问地址:http://www.cnblogs.com/yubaolee/p/BestLinqQuery.html
linq联合查询
内联查询
内联是一个实际使用频率很高的查询,它查询两个表共有的且都不为空的部分
from user in UserInfo
join c in Classes on user.Id equals c.UserId
select new
{
user.UserName,
user.Id,
c.ClassName
}
查询结果

对应的SQL语句
SELECT [t0].[UserName], [t0].[Id], [t1].[ClassName]
FROM [UserInfo] AS [t0]
INNER JOIN [Class] AS [t1] ON [t0].[Id] = [t1].[UserId]
左联查询
左联应该是联合查询中使用频率最高的查询。它以左表为准,进行联合查询。如果右表中不存在对应的结果,则置空。(注意:在Linq中是不存在右联连的说法,因为右联无非是把左边的表移动到右边,查询的结果与左联是一样的)
from user in UserInfo
join c in Classes on user.Id equals c.UserId into temp
from c in temp.DefaultIfEmpty()
select new
{
user.UserName,
user.Id,
c.ClassName
}
查询结果

对应SQL语句
SELECT [t0].[UserName], [t0].[Id], [t1].[ClassName] AS [ClassName]
FROM [UserInfo] AS [t0]
LEFT OUTER JOIN [Class] AS [t1] ON [t0].[Id] = [t1].[UserId]
!注意一下左联那个【temp】,它其实是一个IEnumerable集合。所以我们可以得到到左联的另一种结果:
from user in UserInfo
join c in Classes on user.Id equals c.UserId into temp
select new
{
user,
temp
}
查询结果(为了更明确表达集合,在Class表里特别加了一条记录,所以class那边共有3条)

对应SQL语句,与左联的SQL基本一样,但多了一个统计行数的列
SELECT t0.*, [t1].[Id] AS [Id2], t1.*, (
SELECT COUNT(*)
FROM [Class] AS [t2]
WHERE [t0].[Id] = [t2].[UserId]
) AS [value]
FROM [UserInfo] AS [t0]
LEFT OUTER JOIN [Class] AS [t1] ON [t0].[Id] = [t1].[UserId]
全联接
全联连是得到两个表的交叉结果(在SQL中称为cross join),这种联连方式得到的结果在没有过滤条件的情况下,基本没什么用。看看即可,代码如下:
from user in UserInfo
from c in Classes
select new
{
user.UserName,
user.Id,
c.ClassName
}
查询结果

对应SQL语句
SELECT [t0].[UserName], [t0].[Id], [t1].[ClassName]
FROM [UserInfo] AS [t0], [Class] AS [t1]
合并(Union)
这种查询其实也很少用,但在某些变态业务需求下会非常有用,注意查询的结果。它是合并两个表相同列数的结果,并且如果结果中有相同的行,那么只取一行记录。
(
from userinfo in UserInfo
select new {
Id = (System.Int32?)userinfo.Id,
Name = userinfo.UserName
}
).Union
(
from c in Classes
select new {
Id = (System.Int32?)c.UserId,
Name = c.ClassName
}
)
查询结果

对应SQL语句
SELECT [t0].[Id] AS [value], [t0].[UserName]
FROM [UserInfo] AS [t0]
UNION
SELECT [t1].[UserId] AS [value], [t1].[ClassName]
FROM [Class] AS [t1]
Linq 分组查询
分组查询(group by)也是我们在实际项目中一个常用的操作,查询操作如下:
from c in Classes
group c by c.UserId into temp
select temp
查询结果

注意一下查询结果,外层是一个我们常用的IQueryable<T>,里面是一个类似Dictionary的K-V集合。简单点说Group返回的是一个集合的集合,因此输出时需用双重循环。
我们在使用它的结果时,应该这样调用:
var result = from c in _context.Classes
group c by c.UserId
into temp
select temp; foreach (var c in result)
{
Console.WriteLine(c.Key);
foreach (var citem in c)
{
Console.WriteLine(citem.ClassName);
}
}
实体增加字段处理
我在本文例子中的UserInfo实体类如下:
public partial class UserInfo
{
public int Id { get; set; }
public string UserName { get; set; }
public string UserType { get; set; }
public int Money { get; set; }
}
现在我想在该实体中类中添加一个属性。为了保持原实体类的纯洁。我添加一个新的partial类:
public partial class UserInfo
{
/// <summary>
/// 测试扩展属性
/// </summary>
public string UserExt
{
get { return UserName + ":" + UserType; }
}
}
然后我们用EF访问一下,发现是可以访问的:

但如果我们这样使用时:
from user in _context.UserInfoes
select new
{
user.Id,
user.UserExt
};
会发现编译是没有问题的。但运行时会出现下面异常:

具体错误信息如下: The specified type member 'UserExt' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
即"UserExt"类型并不能被linq支持。因为在进入到foreach进行真正取数据之前。EF已经把linq转成SQL语句,而UserExt会被转成对应的数据库字段。因为数据库中并没有该字段,所以会出现这个问题。解决的方法很简单:
from user in _context.UserInfoes.ToList()
select new
{
user.Id,
user.UserExt
};
即先执行ToList(),提前让linq进行执行,生成UserInfo集合,这样就可以正常访问UserExt了。别看这个小小的改动。在多表联查过滤字段的情况下,你会体会到无尽的妙处!
你可能会想到一个问题,如果我再加一个完整的属性会出现什么情况?
public partial class UserInfo
{
public string UserExt
{
get { return UserName + ":" + UserType; }
}
//新增一个完整的属性
public string UserExt2 { get; set; }
}
上面的UserExt2是我们新加入的一个属性,现在我们来执行一下查询。我想真正去研究过Linq的人肯定知道结果了。

在Linq操作中实体中的属性必须在配置映射时指定。我们的数据库中当然没有UserExt2这个字段,所以增加Ignore标识,或调用一下:
this.Ignore(t => t.UserExt2);
.NET深入实战系列—Linq to Sql进阶的更多相关文章
- Linq实战 之 Linq to Sql及Entity Framework操作详解
Linq实战 之 Linq to Sql及Entity Framework操作详解 一:linq to db的框架 1. linq to sql 2. linq to ado.net entity f ...
- Linq To Sql进阶系列(六)用object的动态查询与保存log篇
动态的生成sql语句,根据不同的条件构造不同的where字句,是拼接sql 字符串的好处.而Linq的推出,是为了弥补编程中的 Data != Object 的问题.我们又该如何实现用object的动 ...
- SCCM 2012 R2实战系列之一:SQL安装
大家好,从今天开始跟大家一起分享自己学习SCCM 2012 R2的一些心得和具体的部署配置,希望能帮到大家.由于SCCM部署的步骤比较复杂,内容也比较多,所以我把SCCM整个部署过程分为以下三个章节: ...
- MySQL架构优化实战系列4:SQL优化步骤与常用管理命令
- .NET面试题系列[14] - LINQ to SQL与IQueryable
.NET面试题系列目录 名言警句 "理解IQueryable的最简单方式就是,把它看作一个查询,在执行的时候,将会生成结果序列." - Jon Skeet LINQ to Obje ...
- LINQ to SQL 系列 如何使用LINQ to SQL插入、修改、删除数据
http://www.cnblogs.com/yukaizhao/archive/2010/05/13/linq_to_sql_1.html LINQ和 LINQ to SQL 都已经不是一个新事物了 ...
- SQL Server 性能优化实战系列(二)
SQL Server datetime数据类型设计.优化误区 一.场景 在SQL Server 2005中,有一个表TestDatetime,其中Dates这个字段的数据类型是datetime,如果你 ...
- LINQ to SQL 系列 如何使用LINQ to SQL插入、修改、删除数据 (转)
http://www.cnblogs.com/yukaizhao/archive/2010/05/13/linq_to_sql_1.html LINQ和 LINQ to SQL 都已经不是一个新事物了 ...
- LINQ系列:LINQ to SQL Where条件
1. 单一条件查询 var expr = context.Products .Where(p => p.ProductName == "LINQ to SQL"); SELE ...
随机推荐
- iOS总结_UI层自我复习总结
UI层复习笔记 在main文件中,UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是 ...
- Android中手机录屏并转换GIF的两种方式
之前在博文中为了更好的给大家演示APP的实现效果,本人了解学习了几种给手机录屏的方法,今天就给大家介绍两种我个人用的比较舒服的两种方法: (1)配置adb环境后,使用cmd命令将手机界面操作演示存为视 ...
- 前端学HTTP之Web主机托管
前面的话 对内容资源的存储.协调以及管理的职责统称为Web主机托管.主机托管是Web服务器的主要功能之一.保存并提供内容,记录对内容的访问以及管理内容都离不开服务器.如果不想自行管理服务器所需的软硬件 ...
- 使用Oracle官方巡检工具ORAchk巡检数据库
ORAchk概述 ORAchk是Oracle官方出品的Oracle产品健康检查工具,可以从MOS(My Oracle Support)网站上下载,免费使用.这个工具可以检查Oracle数据库,Gold ...
- MFC中如何画带实心箭头的直线
工作中遇到话流程图的项目,需要画带箭头的直线,经过摸索,解决:思路如下: (1) 两个点(p1,p2)确定一个直线,以直线的一个端点(假设p2)为原点,设定一个角度 (2)以P2为原点得到向量P2P1 ...
- c++ pair 使用
1. 包含头文件: #include <utility> 2. pair 的操作: pair<T1,T2> p; pair<T1,T2> p(v1,v2); pai ...
- linux服务器开发一 基础
注:本文仅限交流使用,请务用于商业用途,否则后果自负! Linux 1.Linux介绍 Linux是类Unix计算机操作系统的统称. Linux操作系统的内核的名字也是“Linux”. Linux这个 ...
- Hilbert-Huang Transform(希尔伯特-黄变换)
在我们正式开始讲解Hilbert-Huang Transform之前,不妨先来了解一下这一伟大算法的两位发明人和这一算法的应用领域 Section I 人物简介 希尔伯特:公认的数学界“无冕之王”,1 ...
- 周末聊聊IT人员的人脉观:关于帮妹子找兼职有感
背景: 前几天,有个认识了好几年的网友,现在是大学生,在厦门读大一,说和她同学要一起到广州找兼职,看我有没有介绍. 像我这么积极热心善良的人,就说帮她找找看,结果问了几次,没消息,只好诚实的回复人家, ...
- HTML5- Canvas入门(五)
今天要介绍的是canvas对图形对象的操作,包括图像.视频绘制,和操作像素对象的方法. 图片/视频的绘制 在canvas中,我们可以通过 drawImage() 的方法来绘制图片或视频文件,其语法为: ...