linq介绍及工作中应用两例——左联与内联,linq循环方法

  • A+
所属分类:.NET技术
摘要

目录1 linq介绍1.1 linq产生背景1.2 linq使用范围1.3 linq核心程序集1.4 linq架构图1.5 linq使用形式对比1.5.1 linq To Objects1.5.2 linq To Xml1.5.3 linq To Sql1.5.4 LINQ to DataSets1.5.5 小结2.linq To Objects实际应用两例2.1左联与内联2.1.1 本质区别2.1.2 左联应用2.1.2.1 程序示例2.1.2.2 程序解释2.1.2.3 左联内联比对2.1.3 内联应用2.1.3.1 程序示例2.1.3.2 程序解释2.1.3.3 左联内联比对2.1.3.4 左联内联代码比较2.2 linq循环方法2.2.1 程序代码2.2.2 代码应用场景2.2.3 小结3.总结

1 linq介绍

1.1 linq产生背景

一个应用服务后台程序,肯定会需要格式各样的数据检索跟操作,而这些数据在过去的这些年里一般都会包含在关系型数据库或者xml文件中。
.Net3.5版本发行之前,传统的数据源访问方式就是直接对数据库或者xml文件进行检索操作。在.Net3.5 Visual Studio 2008版本之后,微软创新地新增了linq(Language INtegrated Query)语法,也因此增加了一种传统信息存储检索之外的一种内存数据处理机制。
举个例子,你可以创建1个list,存几百个整型数据,你可以写linq表达式,来检索子集(比如偶数子集,奇数子集等)。

1.2 linq使用范围

  • linq语法统一了对于数据源的查询标准,概念,包括关系型数据库,xml文件喝内存级别的数据结构。你可以用linq同样的语法,去查询xml文件跟关系型数据库或者内存数据结构;
  • linq在关系型数据,与对象之间起到了桥梁作用(可通过linq循环方法实现);

1.3 linq核心程序集

程序集名称 描述
System.LINQ 提供linq查询的一些类跟接口
System.Collections.Generic 允许用户创建泛型集合以保证更好的类型安全与性能
System.Data.LINQ 提供了用linq来访问关系型数据库的功能(LINQ TO SQL)
System.XML.LINQ 提供了用linq来访问XML文件的功能(LINQ TO XML)
System.Data.Linq.Mapping 将类指定为与数据库关联的实体类

1.4 linq架构图

linq介绍及工作中应用两例——左联与内联,linq循环方法

  • LINQ to Objects 处理的是内存数据,任何类都能实现IEnumerable<T>集合接口(在System.Collections.Generic命名空间),然后就可以用标准的linq语法进行查询检索了。
  • LINQ to ADO.NET 处理外部数据源,基于ado.Net去连接数据表获得 IEnumerable<T> or IOueryable<T>(在System.Linq命名空间)数据,然后就可以使用linq语法进行适配检索。这一功能在System. Data.Linq 命名空间实现。
  • LINQ to XML 统一简化了xml文件的操作,命名空间是 System.Xml.Linq。

1.5 linq使用形式对比

1.5.1 linq To Objects

string[] instructors = { "Aaron", "Fritz", "Keith", "Scott" };  IEnumerable<string> query = from n in instructors                             where n.Length == 5                             orderby n descending                             select n.Length; 

1.5.2 linq To Xml

XElement instructors = XElement.Parse(                @"<instructors>                    <instructor>Aaron</instructor>                    <instructor>Fritz</instructor>                    <instructor>Keith</instructor>                    <instructor>Scott</instructor>                  </instructors>"             );  IEnumerable<string> query = from n in instructors.Elements("instructor")                             where n.Value.Length == 5                             orderby n.Value descending                             select n.Value;  foreach (string name in query) {     Console.WriteLine(name); }  

1.5.3 linq To Sql

类定义

[Table(Name = "dbo.Customers")] public partial class Customer {                   [Column(IsPrimaryKey = true)]     public string CustomerID     {         get         {             return this._CustomerID;         }         set         {             if ((this._CustomerID != value))             {                 this._CustomerID = value;             }         }                         }     private string _CustomerID;      [Column]     public string CompanyName     {         get         {             return this._CompanyName;         }         set         {             if ((this._CompanyName != value))             {                 this._CompanyName = value;             }         }     }      // ... and so on } 

linq语法

IEnumerable<Customer> customers =     from c in context.Customers     where c.Country == "France"     orderby c.CustomerID ascending     select c;  foreach (Customer c in customers) {     Console.WriteLine(c.CustomerID); } 

1.5.4 LINQ to DataSets

SqlDataAdapter adapter = new SqlDataAdapter(                             "SELECT * FROM Customers",                             _connectionString); DataTable customers = new DataTable("customers"); adapter.Fill(customers);  int countOfFrenchCustomers =     (from c in customers.AsEnumerable()      where c.Field<string>("Country") == "France"      select c).Count(); 

1.5.5 小结

以上可看出,linq语法规范形式统一,不同的核心库会有一些基元元素的不同方法。使用语法一致。
备注:工作原因,本文后续将详细介绍内存数据结构进行代码示例,xml文件与关系型数据库只做形式上的比较,不作验证,读者感兴趣的可自行深入研究

2.linq To Objects实际应用两例

2.1左联与内联

2.1.1 本质区别

  • 左联即使右表为空还是能显示左表;内联如果右表为空,左表不显示;

2.1.2 左联应用

2.1.2.1 程序示例

          //删除ipbox表数据          dbContent.IPBox.RemoveRange(_ipboxDBList);          //AIC表数据           var aics = (from a in _ipboxDBList join b in dbContent.Aic.AsNoTracking() on a.Id equals b.ParentID                 select new Aic             {               ParentID = a.Id,               Id = b.Id             }).ToList();              if (aics != null) { dbContent.Aic.RemoveRange(aics); } 

2.1.2.2 程序解释

ipbox是设备箱表,aic是ipbox的一个采集属性,是ipbox的子表,前者与后者是1对多的关系。ipbox必然存在情况下,aic不一定存在。

2.1.2.3 左联内联比对

如果此时采用左联方式,ipbox存在记录的条件下,对应的aic不存在,但却也能检索出数据,只是aic的id为空,parentId(ipbox的id)却有值。去aic表里删除,缺少对应记录,缺少主键,数据库就会抛出异常。
此时采用内联方式,aic如果不存在,则没有记录,异常问题解决。

2.1.3 内联应用

2.1.3.1 程序示例
 //关联设备箱舱门权限查询,返回分页列表  var list = (from c in DataList              join i in _dbContent.IPBox on c.IpboxId equals i.Id              join a in _dbContent.Area on i.AreaID equals a.Id              join manu in _dbContent.Manufacturer on c.ManufId equals manu.Id              join role in _dbContent.IPBoxCabinRule.Where(b => b.UserId.ToString() == UserId) on i.Id equals role.IpboxId              //采用左联方式删除型号时,就不会筛选不出摄像头              join model in _dbContent.CameraModel on c.ModelId equals model.Id               into temp from info in temp.DefaultIfEmpty(new CameraModel {  Id=0,Code=null})                              select new CameraViewModel              {                  Id = c.Id,                  Code = c.Code,                  Name = c.Name,                  Ip = c.Ip,                  rtuId = c.rtuId,                  Status = c.Status,                  InstallTime = c.InstallTime,                  UserName = c.UserName,                  Password = c.Password,                  rtspurl = c.rtspurl,                  OperCompanyId = c.OperCompanyId,                  OperCompanyName = c.OperCompanyName,                  Enable = c.Enable,                  Remark = c.Remark,                  Type = c.Type,                  CameraType = c.CameraType,                  OutputChannel = c.OutputChannel,                  AreaName = a.AreaName,                  AreaId = i.AreaID,                  CameraModelCode = info.Code,                  CameraModelId = info.Id ,                  ManufacturerName = manu.Name,                  ManufacturerId = manu.Id,                  IpboxName = i.IPBoxName,                  IpboxId = i.Id,                  OperPersonId = c.OperPersonId,                  OperPersonName = c.OperPersonName,                  CreateTime = c.CreateTime              }).ToList();  
2.1.3.2 程序解释

摄像头表DataList,与其关联表CameraModel,进行左联,返回数据给前端作列表展示。

2.1.3.3 左联内联比对

如果此时采用内联方式,删除摄像头型号的时候,摄像头记录存在就不能被有效检索出来。
因此此处应采用左联方式,即使摄像头型号为空,摄像头记录依然能返回。

2.1.3.4 左联内联代码比较

  • 左联代码如下,大意为,如果有数据放入temp,如果为空则new CameraModel { Id=0,Code=null},因此不会影响dataList有效记录的返回。
             //采用左联方式删除型号时,就不会筛选不出摄像头              join model in _dbContent.CameraModel on c.ModelId equals model.Id               into temp from info in temp.DefaultIfEmpty(new CameraModel {  Id=0,Code=null}) 
  • 内联代码,比较的简单粗暴,但是如果摄像头型号被删除,则摄像头本身记录也无法被检索出来。
 join model in _dbContent.CameraModel on c.ModelId equals model.Id 

2.2 linq循环方法

2.2.1 程序代码

            //  linq方法语法:              AreaViewModeList.ForEach(m =>                 {                     var Temp = _areaList.FirstOrDefault(n => n.Id == m.areaCode);                     if (Temp != null)                     {                         m.areaName = Temp.AreaName;                     }                 } 

2.2.2 代码应用场景

_areaList是区域表包含了区域类,该类内的字段areaCode与AreaName的关系是一一对应的字典表关系。而AreaViewModeList里的每个实例需要根据_areaList实例的areaCode来检索出对应的AreaName并且赋值给AreaViewModeList里的每个实例的AreaName字段。

2.2.3 小结

linq在关系型数据,与对象之间起到了桥梁作用。

3.总结

以上是我对linq的基本介绍,与工作中遇到linq的总结。linq的使用需要在工作中不断思考与总结,融汇贯通,他能在内存列表级数据处理上发挥大作用。

参考网站:
Using LINQ With C#
Introduction To LINQ


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://www.cnblogs.com/JerryMouseLi/p/13356790.html