.NET深入实战系列—Linq to Sql进阶

.NET深入实战系列—Linq to Sql进阶

最近在写代码的过程中用到了Linq查询,在查找资料的过程中发现网上的资料千奇百怪,于是自己整理了一些关于Linq中容易让人困惑的地方。

本文全部代码基于:UserInfo与Class两个表,其中Class中的UserId与UserInfo中的Id对应

image

 本文唯一访问地址: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  
} 

查询结果

image

对应的SQL语句

SELECT [t0].[UserName], [t0].[Id], [t1].[ClassName]  
FROM [UserInfo] AS [t0]  
INNER JOIN [Class] AS [t1] ON [t0].[Id] = [t1].[UserId] 

左联查询


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    
}

查询结果

image

对应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条)

image

对应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  
}  

查询结果

image

对应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  }  
)  

查询结果

image

对应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 

查询结果

image

 

注意一下查询结果,外层是一个我们常用的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访问一下,发现是可以访问的:

image

但如果我们这样使用时:

from user in _context.UserInfoes
select new
{user.Id,user.UserExt
};

会发现编译是没有问题的。但运行时会出现下面异常:

image

具体错误信息如下: 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的人肯定知道结果了。

image

在Linq操作中实体中的属性必须在配置映射时指定。我们的数据库中当然没有UserExt2这个字段,所以增加Ignore标识,或调用一下:

this.Ignore(t => t.UserExt2); 

  

转载于:https://www.cnblogs.com/shasha-611/p/7448625.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/416041.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

11G数据库导入10G的操作实践

Oracle11g数据库导入Oracle10g数据库操作笔记用exp、imp命令时进行11g备份&#xff0c;导入10g的时候会抛错&#xff1a;不是有效的导出文件&#xff0c;头部验证失败&#xff1b;未成功终止导入。我今天就遇到了这种情况&#xff0c;搭建测试环境时&#xff0c;有一个项目使用…

软件测试个人心得总结

做测试有几年的时间了&#xff0c;很少这样了完整的来总结一些东西&#xff0c;最近有时间小小的总结了一下&#xff0c;针对公司有些项目提交测试时&#xff0c;存在的一些问题&#xff0c;谈谈个人的一些看法&#xff0c;比如没有需求&#xff0c;也没什么任何文档或有少量不…

【BZOJ1003】物流运输

1003: [ZJOI2006]物流运输 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 8273 Solved: 3481[Submit][Status][Discuss]Description 物流公司要把一批货物从码头A运到码头B。由于货物量比较大&#xff0c;需要n天才能运完。货物运输过程中一般要转停好几个码头。物流公司通…

mongoose日期 时间 范围查询

需要知道的两个修饰符 $gte和$lt $gte (greater-than)$lt (less-than) 写法如下 const start new Date(2018, 3, 1); const end new Date(2018, 4, 1); db.posts.find({created_on: {$gte: start, $lt: end}});

Oracle rman备份和还原恢复数据库

1、切换服务器归档模式&#xff0c;如果已经是归档模式可跳过此步&#xff1a;%sqlplus /nolog &#xff08;启动sqlplus&#xff09;  SQL> conn / as sysdba &#xff08;以DBA身份连接数据库&#xff09;  SQL> shutdown immediate; &#xff08;立即关闭数据库&a…

JavaScript 随意整理2

08.29 # 全局对象* escape/unescape() 对特殊字符编码/解码* encodeURI / decodeURL 对url进行编码/解码* encodeURIComponent / decodeURIComponent 对URL解码/解码* eval() 把字符串当做代码执行# JSON对象* parse() 把josn字符串转换为对象* stringify() 把对…

css scale 缩放基准点

使用transform-origin来进行控制 在使用transform方法进行文字或图像的变形时&#xff0c;是以元素的中心点为基准点进行的。使用transform-origin属性&#xff0c;可以改变变形的基准点。 用法&#xff1a;transform-origin: 10px 10px; 共两个参数&#xff0c;表示相对左上角…

闪回区设置问题

oracle10g提供了一个叫做闪回恢复区(Flashback recovery area)的新特性&#xff0c;可以将所有恢复相关的文件&#xff0c;比如flashback log,archive log,backup set等&#xff0c;放到这个区域集中管理。 查看闪回区内容及使用情况&#xff1a; select * from v$flash_recov…

多主机Docker容器的VLAN划分

原文发表于cu&#xff1a;2016-06-06 参考文档&#xff1a; Docker网络的4种模式&#xff0c;pipework/ovs的简单使用等&#xff1a;http://www.infoq.com/cn/articles/docker-network-and-pipework-open-source-explanation-practice Dockerpool全文档&#xff1a;https://yea…

css p 文本不换行,超出文字显示省略号

.text {// 文本强制不换行white-space: nowrap;// 文本溢出显示省略号text-overflow: ellipsis;// 溢出的部分隐藏overflow: hidden; }

oracle监听无法启动常用解决办法

在cmd下使用lsnrctl start无法启动监听程序提示&#xff1a;TNS-12560: TNS: 协议适配器错误在cmd下进入lsnrctl&#xff0c;输入start提示&#xff1a;TNS-12557: Message 12557 not found; No message file for productNETWORK, facilityTNSns secondary err code: 12560请检…

mongodb 高级查询 统计记录条数

使用count()方法查询表中的记录条数&#xff0c;例如&#xff0c;下面的命令查询表users的记录数量&#xff1a; db.users.find().count();

SQL语句优化

【数据库优化的目的】 1.避免出现页面访问错误 由于数据库连接timeout产生页面5XX错误。 由于慢查询造成页面无法加载。 由于阻塞造成数据无法提交。 2.增加数据库的稳定性 很多数据库问题都是由于低效的查询引起的。 3.优化用户体验 流畅的访问速度。 良好的网站功能体验。 【…

ORA-27101 shared memory realm does not exist 错误处理

ORA-27101 错误处理 racle Database的主机被异常关机&#xff0c;重新启动电脑&#xff0c;Database报ORA-27101 shared memory realm does not exist 错误&#xff0e;可能是windows的oracle service 损坏&#xff0c;可以重建service试试是否可以修复。删除Service&#xff1…

js 获取 当天凌晨时间

需要进行时间比较的时候&#xff0c;一般会遇到从凌晨开始算 new Date(new Date().setHours(0, 0, 0, 0))