语言集成查询LINQ
来源:互联网 发布:linux 驱动精灵 编辑:程序博客网 时间:2024/05/15 05:26
目录
一、LINQ概述
1、LINQ简介
2、体系结构
3、基础回顾(匿名类型、扩展方法、拉姆达表达式)
4、LINQ查询幕后的实现
(1)、查询语法(LINQ查询)
(2)、方法语法(Lambda表达式)----与(1)等价
(3)、方法语法(委托类型/匿名方法)----与(1)等价
(4)、方法语法(委托类型/具体方法)----与(1)等价
5、LINQ延迟执行
(1)、LINQ延迟执行
(2)、改进LINQ延迟执行
二、LINQ to SQL
1、LINQ to SQL 简介
2、实体类映射
3、DataContext数据上下文对象
4、定义基本关系
(1)、一对多关系
(2)、多对一关系
5、对象关系设计器
(1)、查询代码片段
(2)、新增代码片段
(3)、更新代码片段
(4)、删除代码片段
(5)、LINQ to SQL示例
三、LINQ to XML
1、.NET Framework3.5中新的XML对象
2、LINQ查询XML代码片段
四、LINQ to DataSet
1、查询一个表代码片段
2、使用聚合函数代码片段
3、查询两个表代码片段
4、查询类型化DataSet
5、检测空字段代码片段
6、将结果保存到DataTable代码片段
五、其他
1、LINQ to SQL示例
2、杂项
3、过滤泛型List示例
正文
一、LINQ概述
1、LINQ简介
● LINQ的全称:Language Integrated Query。语言集成查询。
● 不采用特定于关系数据库或者XML的专有方案,而采用通用方案来解决各种信息资源的访问与整合问题。
(处理数据库,就必须理解SQL;处理XML,就必须理解Xpath、Xquery、XSLT这样的技术;处理DataSet,则需要了解ADO.NET中可以使用的各种类和特性。而LINQ提供了统一的数据视图,从而不需要考虑数据的形式和结构。)
● 在LINQ中,查询成为编程语言的一部分。这使得查询表达式可以得到编译时的语法检查,智能感知(InteliSense)的好处。
2、体系结构
如图所示:
● 最底层包含应用程序可以操作的各种数据源。包括:对象、关系数据库、XML。
● 倒数第二层是LINQ支持的数据源:LINQ to Objects、LINQ to DataSet、LINQ to SQL、LINQ to Entities和LINQ to XML。
● LINQ支持的数据源也称为LINQ提供程序;这些LINQ提供程序将以VB或C#表达的查询转换为该数据源的本地语言。为了通过LINQ访问所有这些数据源,开发人员可以使用C#或VB并编写LINQ查询。
3、基础回顾(匿名类型、扩展方法、拉姆达表达式)
● 匿名类型 :在不需要正式定义类的情况下定义数据类型。实际上,匿名类型是MS专门为LINQ设计的新功能。更多内容参见:匿名类型的相关文档。
● 扩展方法:扩展已有类的功能,而不需要创建该类的子类。扩展方法的出现,很重要的一个原因也是LINQ的出现。更多内容参见:扩展方法的相关文档。
● 拉姆达表达式:实现类似于匿名方法同样的效果。匿名方法,将代码直接与委托实例相关联。更多内容参见:匿名方法和Lambda表达式的相关文档。
4、LINQ查询幕后的实现
(1)、查询语法(LINQ查询)
string[] names ={
"Burke","Connor","Frank","Everett","Albert","George","Harris","David" };
IEnumerable<string> query =
from s in names
where s.Length == 5
orderby s
select s.ToUpper();
(2)、方法语法(Lambda表达式)----与(1)等价
IEnumerable<string> query = names
.Where(s => s.Length == 5)
.OrderBy(s => s)
.Select(s => s.ToUpper());
● s => s.Length == 5 | s => s | s => s.ToUpper() 是三个Lambda表达式。
● Where()、OrderBy()、Select()是静态类Enumerable的静态方法,是泛型接口IEnumerable<T>的扩展方法。
调用静态类的扩展方法
扩展方法允许这样调用
返回值类型
Enumerable.Where
(names, s => s.Length == 5);
names.Where
(s => s.Length == 5)
IEnumerable<T>
Enumerable.OrderBy
(names, s => s);
names.OrderBy
(s => s)
IOrderedEnumerable<T>
(实现了IEnumerable<T>接口)
Enumerable.Select
(names, s => s.ToUpper());
names.Select
(s => s.ToUpper())
IEnumerable<T>
◆ Where()方法需要的参数类型为: Func<TSource, bool>(委托类型)。
TSource:集合中元素的类型。bool:返回值类型。
◆ OrderBy()方法需要的参数类型为:Func<TSource, TKey>(委托类型)。
TSource: 集合中元素的类型。Tkey:返回值类型。
◆ Select()方法需要的参数类型为: Func<TSource, TResult>(委托类型)。
TSource: 集合中元素的类型。TResult:返回值类型。
● 更多内容参见:Where()、OrderBy()、Select()方法的定义。
(3)、方法语法(委托类型/匿名方法)----与(1)等价
Func<string, bool> filter = delegate(string s) { return s.Length == 5; };
Func<string, string> extract = delegate(string s) { return s; };
Func<string, string> project = delegate(string s) { return s.ToUpper(); };
IEnumerable<string> query =
names.Where(filter).OrderBy(extract).Select(project);
(4)、方法语法(委托类型/具体方法)----与(1)等价
Func<string, bool> filter = Method1;
Func<string, string> extract = Method2;
Func<string, string> project = Method3;
IEnumerable<string> query =
names.Where(filter).OrderBy(extract).Select(project);
bool Method1(string s) { return s.Length == 5; }
string Method2(string s) { return s; }
string Method3(string s) { return s.ToUpper(); }
5、LINQ延迟执行
(1)、LINQ延迟执行
var result =
from c in Products
where c.Price > 500
select c;
foreach (Product p in result)
{
……
}
● 查询变量result只是对linq查询的一个描述,而非执行结果。换言之,linq查询并不立即执行得到结果,而是将查询缓存在变量result中。那么result是什么类型呢?IQueryable<T>。public interface IQueryable<T> : IEnumerable<T>, IQueryable, IEnumerable
● IQueryable<T>只是查询表示,类似于SqlCommand等命令表示,真正的查询执行要依赖于在其上的调用操作。SqlCommand调用ExecuteNonQuery()、ExecuteReader()等方法将导致查询的执行;foreach语句会导致IQueryable<T>上的方法GetEnumerator()执行,从而导致查询的执行,并将返回结果IEnumerator<T>。
● 缓存查询,而不立即执行的这种现象称作延迟执行。
● 延迟执行如果使用不当会导致各种程序效率问题。
(2)、改进LINQ延迟执行
var result =
from c in Products
where c.Price > 500
select c;
var list = result.ToList<Product>;
foreach (Product p in list)
{
……
}
通过调用ToList或者ToArray方法,可以直接执行linq查询,将查询结果缓存在list变量中。
二、LINQ to SQL
1、LINQ to SQL 简介
● 面向对象领域,一切围绕对对象(字段、方法、引用)。
关系型数据库领域,一切围绕表格数据(行、列、关系)。
● LINQ将关系数据库映射为对象模型。开发人员不是直接操作数据库,而是操作表示数据库的对象模型。对对象模型执行更改之后,将其提交给数据库执行。
● LINQ To SQL是ADO.NET的一个重要组件,而非完全替代品。
2、实体类映射
[Table(Name = "Category")]
public class Category
{
[Column(IsPrimaryKey=true)]
public string CategoryId;
[Column]
public string Name;
[Column]
public string Descn;
}
[Table]特性表示将类Category与数据库中的表Category相对应。
[Column]特性则对应数据库中的列。
3、DataContext数据上下文对象
DataContext db = new DataContext(@"server=./sqlexpress;database=pubs;uid=sa;pwd=123;");
Table<Category> Categorys = db.GetTable<Category>();
var result =
from c in Categorys
select c;
DataContext类非常类似于数据库连接对象,但它为LINQ to SQL提供了更多支持。
4、定义基本关系
(1)、一对多关系
[Table(Name = "Category")]
public class Category
{
……
private EntitySet<Product> products;
[Association(Storage="products",OtherKey="CategoryId")]
public EntitySet<Product> Products
{
get { return this.products; }
set { this.products.Assign(value); }
}
}
Products映射了Category与Product之间的一对多关系。
(2)、多对一关系
[Table(Name="Product")]
public class Product
{
……
private EntityRef<Category> category;
[Association(Storage = "category", ThisKey = "CategoryId")]
public Category Category
{
get { return this.category.Entity; }
set { this.category.Entity = value; }
}
}
Category映射了Product与Category之间的多对一关系。
5、对象关系设计器
● 对象关系设计器将自动完成实体类映射、定义基本关系、创建DataContext子类等工作。
● 在项目中添加新项“LINQ to SQL类”,将创建默认名称为“DataClasses1.dbml”的文件。
(1)、查询代码片段
//查询居住在加利福尼亚的所有作者
void Method1()
{
DataClasses1DataContext database = new DataClasses1DataContext();
var authors = from a in database.authors
where a.state == "CA"
select new
{
Name = a.au_fname + " " + a.au_lname
};
foreach (var a in authors)
Console.WriteLine(a.Name);
}
(2)、新增代码片段
//插入新行(一个表)
void Method2()
{
DataClasses1DataContext database = new DataClasses1DataContext();
authors a = new authors()
{
au_id = "123-45-6789",
au_fname = "wang",
au_lname = "cheng",
phone = "13701362855"
};
database.authors.InsertOnSubmit(a);//InsertOnSubmit()方法只影响对象模型
database.SubmitChanges();//使用SubmitChanges()方法将更改保存到数据库
}
//插入新行(多个表)
void Method3()
{
//插入来自于新作者(author)的新书(title)的书名(authortitle)
DataClasses1DataContext db = new DataClasses1DataContext();
authors a = new authors()
{
au_id = "234-56-7890",
au_fname = "zhang",
au_lname = "ting",
phone = "13811765843"
};
titles t = new titles()
{
title_id = "ZT5555",
title = "C#高级编程(第六版)",
pubdate = System.DateTime.Now,
type = "computer"
};
titleauthor ta = new titleauthor()
{
authors = a,
titles = t
};
db.titleauthor.InsertOnSubmit(ta);//需要指示titleauthor表中的title_id和author_id,LINQ to SQL会自动执行该操作。
db.SubmitChanges();
}
(3)、更新代码片段
//更新行
void Method4()
{
DataClasses1DataContext db = new DataClasses1DataContext();
titles bookTitle =
(from t in db.titles
where t.title_id == "ZT5555"
select t).Single();//Single()方法返回序列中的唯一元素。如果该序列中一个元素也没有,则会跑出异常。
bookTitle.title = "SQL Server 核心技术";
db.SubmitChanges();
}
(4)、删除代码片段
//删除行(一个表)
void Method5()
{
DataClasses1DataContext db = new DataClasses1DataContext();
var author = from a in db.authors
where a.au_id == "123-45-6789"
select a;
if (author.Count() > 0)
{
db.authors.DeleteOnSubmit(author.First());
db.SubmitChanges();
}
}
//删除行(多个表)
void Method6()
{
DataClasses1DataContext db = new DataClasses1DataContext();
string au_id_to_remove = "234-56-7890";
//删除author
var author = from a in db.authors
where a.au_id == au_id_to_remove
select a;
foreach (var a in author)
db.authors.DeleteOnSubmit(a);
//删除titleauthor
var titleauthor = from ta in db.titleauthor
where ta.au_id == au_id_to_remove
select ta;
foreach (var ta in titleauthor)
db.titleauthor.DeleteOnSubmit(ta);
//程序里无论先删除author,还是先删除titleauthor都无所谓
//LINQ会自动先删除titleauthor,再删除author
db.SubmitChanges();
}
(5)、LINQ to SQL示例
LINQ to SQL示例
三、LINQ to XML
1、.NET Framework3.5中新的XML对象
● XDocument对象:这个对象可以创建XML文档。它替代了.NET3.5之前的XmlDocument对象。
Xdocument对象的一个重要成员是Load()方法。这个方法将XML文档加载到内存中。
XDocument xdoc = XDocument.Load(@"C:/Hamlet.xml");
另一个重要成员是Save()方法。可以将xml文档保存到物理文件中。
XDocument xdoc = XDocument.Load(@"C:/Hamlet.xml");
xdoc.Save(@"C:/CopyOfHamlet.xml");
● XElement对象:表示单个元素的对象。
● XNamespace对象:表示XML命名空间。
● XComment对象:将注释添加到XML文档。
● XAttribute对象:用于添加和使用属性。
2、LINQ查询XML代码片段
XDocument LibraryBooks = new XDocument();
LibraryBooks = XDocument.Load("Books.xml");
var query =
from book in LibraryBooks.Descendants("Book")
where book.Element("Publisher").Value == "Wrox"
select book.Element("Title").Value;
Console.WriteLine("Wrox出版的所有书籍");
foreach (var book in query)
Console.WriteLine(book);
四、LINQ to DataSet
1、查询一个表代码片段
EnumerableRowCollection<DataRow> authors =
from author in ds.Tables[0].AsEnumerable()
where author.Field<string>("state") == "CA"
select author;
foreach (DataRow dr in authors)
{
Console.WriteLine("{0} - {1} {2}", dr["au_id"].ToString(), dr["au_fname"].ToString(), dr["au_lname"].ToString());
}
2、使用聚合函数代码片段
var query =
ds.Tables[0].AsEnumerable()
.Count(a => a.Field<string>("state") == "CA");
Console.WriteLine("共{0}个结果", query);
int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var maxOddNum = nums.Where(n => n % 2 == 1).OrderByDescending(n => n).Max();
Console.WriteLine("最大的奇数是:{0}", maxOddNum);
var sumOfNums = nums.Where(n => n % 2 == 1).OrderByDescending(n => n).Sum();
Console.WriteLine("所有奇数的和为:{0}", sumOfNums);
3、查询两个表代码片段
var query =
(from customer in customersTable.AsEnumerable()
join order in ordersTable.AsEnumerable()
on customer.Field<string>("customerID") equals order.Field<string>("customerID")
select new
{
id=customer.Field<string>("customerID"),
CompanyName = customer.Field<string>("CompanyName"),
ContactName = customer.Field<string>("ContactName"),
OrderDate = order.Field<DateTime>("OrderDate"),
ShipCountry = order.Field<string>("ShipCountry")
}).ToList();
dataGridView1.DataSource = query;
4、查询类型化DataSet
向项目中添加新建项DataSet,命名为:TypedCustomerDataSet.xsd。
在服务器资源管理器窗口中,打开希望使用的数据库连接。该示例使用Northwind数据库。
将Customer表拖到TypedCustomerDataSet.xsd的设计界面上。
SqlConnection conn;
SqlCommand cmd;
SqlDataAdapter da;
TypedCustomerDataSet ds = new TypedCustomerDataSet();
conn = new SqlConnection(@"server=.;database=northwind;uid=sa;pwd=sa");
cmd = new SqlCommand("select * from customers;", conn);
da = new SqlDataAdapter(cmd);
da.Fill(ds,"Customers");
var query =
(from customer in ds.Customers
where customer.Country == "USA"
select new
{
customer.CustomerID,
customer.CompanyName,
customer.ContactName,
customer.ContactTitle
}).ToList();
dataGridView1.DataSource = query;
5、检测空字段代码片段
var query =
(from customer in ds.Customers
//where语句中的条件求值时使用了短路方式,因此必须将IsNull()方法放在其他条件之前
//如果没有使用类型化的DataSet,就不需要显示地检查空值
where !customer.IsNull("Region") && customer.Region == "WA"
select new
{
customer.CustomerID,
customer.CompanyName,
customer.ContactName,
customer.ContactTitle
}).ToList();
dataGridView1.DataSource = query;
6、将结果保存到DataTable代码片段
var query =
from customer in ds.Customers
where customer.Country == "USA"
select customer;
//CopyToDataTable()不适用于计划使用匿名类型的查询或执行表连接的查询。
DataTable USACustomers = query.CopyToDataTable();
dataGridView1.DataSource = USACustomers;
五、其他
1、LINQ to SQL示例
创建一个Windows应用程序。
在项目中添加新项LINQ to SQL类,对该项使用默认名称DataClasses1.dbml。
在服务器资源管理器中打开希望使用的数据库连接,在该示例中使用pubs样本数据库。
将以下表拖到DataClasses1.dbml的设计界面上:authors、publishers、titleauthor、titles。
保存DataClasses1.dbml文件。
下面的代码包括查询、新增、更新和删除的功能。
private void Form1_Load(object sender, EventArgs e)
{
Method1();
}
//查询居住在加利福尼亚的所有作者
void Method1()
{
DataClasses1DataContext database = new DataClasses1DataContext();
var authors = from a in database.authors
where a.state == "CA"
select new
{
Name = a.au_fname + " " + a.au_lname
};
foreach (var a in authors)
Console.WriteLine(a.Name);
}
//插入新行(一个表)
void Method2()
{
DataClasses1DataContext database = new DataClasses1DataContext();
authors a = new authors()
{
au_id = "123-45-6789",
au_fname = "wang",
au_lname = "cheng",
phone = "13701362855"
};
database.authors.InsertOnSubmit(a);//InsertOnSubmit()方法只影响对象模型
database.SubmitChanges();//使用SubmitChanges()方法将更改保存到数据库
}
//插入新行(多个表)
void Method3()
{
//插入来自于新作者(author)的新书(title)的书名(authortitle)
DataClasses1DataContext db = new DataClasses1DataContext();
authors a = new authors()
{
au_id = "234-56-7890",
au_fname = "zhang",
au_lname = "ting",
phone = "13811765843"
};
titles t = new titles()
{
title_id = "ZT5555",
title = "C#高级编程(第六版)",
pubdate = System.DateTime.Now,
type = "computer"
};
titleauthor ta = new titleauthor()
{
authors = a,
titles = t
};
db.titleauthor.InsertOnSubmit(ta);//需要指示titleauthor表中的title_id和author_id,LINQ to SQL会自动执行该操作。
db.SubmitChanges();
}
//更新行
void Method4()
{
DataClasses1DataContext db = new DataClasses1DataContext();
titles bookTitle =
(from t in db.titles
where t.title_id == "ZT5555"
select t).Single();//Single()方法返回序列中的唯一元素。如果该序列中一个元素也没有,则会跑出异常。
bookTitle.title = "SQL Server 核心技术";
db.SubmitChanges();
}
//删除行(一个表)
void Method5()
{
DataClasses1DataContext db = new DataClasses1DataContext();
var author = from a in db.authors
where a.au_id == "123-45-6789"
select a;
if (author.Count() > 0)
{
db.authors.DeleteOnSubmit(author.First());
db.SubmitChanges();
}
}
//删除行(多个表)
void Method6()
{
DataClasses1DataContext db = new DataClasses1DataContext();
string au_id_to_remove = "234-56-7890";
//删除author
var author = from a in db.authors
where a.au_id == au_id_to_remove
select a;
foreach (var a in author)
db.authors.DeleteOnSubmit(a);
//删除titleauthor
var titleauthor = from ta in db.titleauthor
where ta.au_id == au_id_to_remove
select ta;
foreach (var ta in titleauthor)
db.titleauthor.DeleteOnSubmit(ta);
//程序里无论先删除author,还是先删除titleauthor都无所谓
//LINQ会自动先删除titleauthor,再删除author
db.SubmitChanges();
}
2、杂项
● 数据库中的一行数据,用linq查询多次,转换成的对象是同一个对象(引用相等)。
● 两次查询同一行数据的中间在数据库对该行数据进行了更改,内存中的对象的值是不发生变化的。
● 过滤泛型List示例:
List<Customer> listCustomerAll;
Customer model;
List<Customer> listTemp = new List<Customer>();
listTemp = listCustomerAll.FindAll(
new Predicate<Customer>(delegate(Customer c) { return c.customerID == model.ID; })
);
- 语言集成查询LINQ
- 语言集成查询(LINQ)
- LINQ,语言级集成查询
- LINQ:语言级集成查询
- [推荐]语言集成查询LINQ入门篇
- 语言集成查询之Linq 入门
- C#笔记14:语言集成查询 (LINQ)
- c#学习笔记---语言集成查询LINQ
- 关于LINQ(语言集成查询)的一些学习笔记
- LINQ,语言级集成查询(Language INtegrated Query)
- [转]LINQ,语言级集成查询(Language INtegrated Query)
- LINQ,语言级集成查询(Language INtegrated Query)简介
- LINQ,语言级集成查询(Language INtegrated Query)
- LINQ——语言级集成查询入门指南
- LINQ,语言级集成查询(Language INtegrated Query)
- 学习语言集成查询--Linq之Lambda表达式学习笔记
- .NET漫游指南-006-语言集成查询LINQ
- 查询语言LINQ--1
- Linkq相关文章
- while循环
- Sql2005的远程连接配置方法
- 获取android联系人信息
- 百钱买百鸡
- 语言集成查询LINQ
- 一个学机械的毕业生令中国人无法安眠的帖子--http://www.21ic.com/wyzt/201012/71551.htm
- C++模板学习--kankan
- Displayable1
- Displayable1
- Draw
- 猜猜看游戏
- Webservice 初体验
- Android ProgressDialog显示线程处理进度