大多数应用程序都是以数据为中心的,但大多数数据存储库都是关系数据库.多年来,设计人员和开发人员基于对象模型设计了应用程序.
对象负责连接数据访问组件 - 称为数据访问层(DAL).这里有三点需要考虑:
应用程序中所需的所有数据都不存储在同一个源中.源可以是关系数据库,某些业务对象,XML文件或Web服务.
访问内存中对象比访问更简单,更便宜来自数据库或XML文件的数据.
访问的数据不直接使用,但需要进行排序,排序,分组,更改等.
因此,如果有一个工具可以轻松访问所有类型的数据,允许从这些不同的数据源加入数据并执行标准数据处理操作,在几行代码中,它会有很大的帮助.
LINQ或语言集成查询就是这样一个工具. LINQ是.Net Framework 3.5及其托管语言的扩展,用于将查询设置为对象.它定义了一种通用语法和编程模型,用于使用通用语言查询不同类型的数据.
关系运算符,如Select,Project,Join,Group,Partition,Set operations等,在LINQ中实现,.Net framework 3.5中的C#和VB编译器支持LINQ语法,可以在不使用ADO.NET的情况下使用已配置的数据存储.
例如,使用C#中的LINQ查询查询Northwind数据库中的Customers表,代码为:
var data = from c in dataContext.Customers where c.Country == "Spain" select c;
其中:
'from'关键字逻辑循环遍历集合的内容.
对集合中的每个对象评估带有'where'关键字的表达式.
'select'语句选择要添加到返回列表中的评估对象.
'' var'关键字用于变量声明.由于返回对象的确切类型未知,它表示将动态推断信息.
可以应用LINQ查询对于从IEnumerable< T>继承的任何数据承载类,此处T是任何数据类型,例如,List< Book>.
让我们看一个例子来理解这个概念.该示例使用以下类:Books.cs
public class Books { public string ID {get; set;} public string Title { get; set; } public decimal Price { get; set; } public DateTime DateOfRelease { get; set; } public static List<Books> GetBooks() { List<Books> list = new List<Books>(); list.Add(new Books { ID = "001", Title = "Programming in C#", Price = 634.76m, DateOfRelease = Convert.ToDateTime("2010-02-05") }); list.Add(new Books { ID = "002", Title = "Learn Java in 30 days", Price = 250.76m, DateOfRelease = Convert.ToDateTime("2011-08-15") }); list.Add(new Books { ID = "003", Title = "Programming in ASP.Net 4.0", Price = 700.00m, DateOfRelease = Convert.ToDateTime("2011-02-05") }); list.Add(new Books { ID = "004", Title = "VB.Net Made Easy", Price = 500.99m, DateOfRelease = Convert.ToDateTime("2011-12-31") }); list.Add(new Books { ID = "005", Title = "Programming in C", Price = 314.76m, DateOfRelease = Convert.ToDateTime("2010-02-05") }); list.Add(new Books { ID = "006", Title = "Programming in C++", Price = 456.76m, DateOfRelease = Convert.ToDateTime("2010-02-05") }); list.Add(new Books { ID = "007", Title = "Datebase Developement", Price = 1000.76m, DateOfRelease = Convert.ToDateTime("2010-02-05") }); return list; } }
使用此类的网页有一个简单的标签控件,可显示书籍的标题. Page_Load事件创建一个书籍列表并使用LINQ查询返回标题:
public partial class simplequery : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { List<Books> books = Books.GetBooks(); var booktitles = from b in books select b.Title; foreach (var title in booktitles) lblbooks.Text += String.Format("{0} <br />", title); } }
执行页面时,标签会显示查询结果:
上述LINQ表达式:
var booktitles = from b in books select b.Title;
等同于以下SQL查询:
SELECT Title from Books
除了目前使用的运算符之外,还有其他几个运算符,它们实现了所有查询条款.让我们看看一些运算符和子句.
SQL中的'join子句'用于连接两个数据表并显示包含两个表中列的数据集. LINQ也有能力做到这一点.要检查这一点,请在上一个项目中添加另一个名为Saledetails.cs的类:
public class Salesdetails { public int sales { get; set; } public int pages { get; set; } public string ID {get; set;} public static IEnumerable<Salesdetails> getsalesdetails() { Salesdetails[] sd = { new Salesdetails { ID = "001", pages=678, sales = 110000}, new Salesdetails { ID = "002", pages=789, sales = 60000}, new Salesdetails { ID = "003", pages=456, sales = 40000}, new Salesdetails { ID = "004", pages=900, sales = 80000}, new Salesdetails { ID = "005", pages=456, sales = 90000}, new Salesdetails { ID = "006", pages=870, sales = 50000}, new Salesdetails { ID = "007", pages=675, sales = 40000}, }; return sd.OfType<Salesdetails>(); } }
在Page_Load事件处理程序中添加代码,使用join子句查询这两个表:
protected void Page_Load(object sender, EventArgs e) { IEnumerable<Books> books = Books.GetBooks(); IEnumerable<Salesdetails> sales = Salesdetails.getsalesdetails(); var booktitles = from b in books join s in sales on b.ID equals s.ID select new { Name = b.Title, Pages = s.pages }; foreach (var title in booktitles) lblbooks.Text += String.Format("{0} <br />", title); }
结果页面如下所示:
'where子句'允许向查询添加一些条件过滤器.例如,如果要查看页数超过500的书籍,请将Page_Load事件处理程序更改为:
var booktitles = from b in books join s in sales on b.ID equals s.ID where s.pages > 500 select new { Name = b.Title, Pages = s.pages };
查询只返回那些页数大于500的行:
这些子句允许对查询结果进行排序.要查询按书价排序的书名,页数和价格,请在Page_Load事件处理程序中编写以下代码:
var booktitles = from b in books join s in sales on b.ID equals s.ID orderby b.Price select new { Name = b.Title, Pages = s.pages, Price = b.Price};
返回的元组是:
let子句允许定义变量并为其分配从数据值计算的值.例如,要计算上述两个销售额的总销售额,您需要计算:
TotalSale = Price of the Book * Sales
为实现此目的,请在Page_Load事件处理程序中添加以下代码片段:
let子句允许定义变量和为其分配从数据值计算的值.例如,要计算上述两个销售额的总销售额,您需要计算:
var booktitles = from b in book join s in sales on b.ID equals s.ID let totalprofit = (b.Price * s.sales) select new { Name = b.Title, TotalSale = totalprofit};
生成的查询页面如下所示: