#1 linq介紹 ##1.1 linq產生背景 一個應用服務後臺程式,肯定會需要格式各樣的數據檢索跟操作,而這些數據在過去的這些年裡一般都會包含在關係型資料庫或者xml文件中。 .Net3.5版本發行之前,傳統的數據源訪問方式就是直接對資料庫或者xml文件進行檢索操作。在.Net3.5 Visua ...
目錄
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 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