都说LINQ(Language Integrated Query)是.NET 3.5中最酷的特性。今天在Visual Studio 2008 Express里尝试了一下,感觉十分震撼!

首先简单地说一下LINQ是干什么的:

  • 在任何数据源上高效地表达查询行为;
  • 将查询结果转换或形成任何形式的结果集;
  • 非常方便地操作这个结果集。

对LINQ这个概念不熟悉的同学可以先看这个例子:

using System;
using System.Collections.Generic;
using System.Linq;

namespace SimpleLinq
{
    
class Program
    {
        
static void Main(string[] args)
        {
            
int[] dataSource = { 123456789 };
            IEnumerable
<int> lessThan5 = from number in dataSource 
                                                     where number 
> 2 && number < 8 
                                                     orderby number descending 
                                                     select number;
            
foreach(int number in lessThan5)
            {
                Console.WriteLine(number.ToString());
            }
            Console.ReadLine();
        }
    }
}

输出结果:

7
6
5
4
3

关键就是这一句:from number in dataSource where number > 2 && number < 8 orderby number descending select number。顾名思义即可,无需多说。

下面是想要演示的LINQ to SQL和ORM(Object-relational mapping)。

1. 打开Visual Web Developer 2008(没有的在这里下载),新建一个网站:

2. 然后将SQL Server 2000的示例数据库NorthWind放到App_Data目录下(没有这个数据库的到这里下载):

3. 下面在App_Code文件夹里创建一个Northwind.dbml文件,这个文件用来包含LINQ to SQL的data model,即一些ORM的信息。

4. 下面生成Northwind数据库的data model,在Database Explorer中将Products和Supliers两张表拖入Northwind.dbml的设计视图即可。注意两张表之间存在一定的关系:

5. 在Default.aspx中创建一个GridView,用来显示数据:

<%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    
<title>LINQ to SQL</title>
</head>
<body>
    
<form id="form" runat="server">
        
<div>
            
<asp:GridView ID="gridView" runat="server" />
        
</div>
    
</form>
</body>
</html>

6. 在Default.aspx.cs中,我们把符合条件的那些Product查出来(查询条件是Product的Suplier位于USA),查询结果按照ProductName字段的字母顺序排序,然后把结果绑定到GridView:

using System;
using System.Linq;
using System.Web.UI;

public partial class _Default : Page 
{
    
protected void Page_Load(object sender, EventArgs e)
    {
        NorthwindDataContext northwind 
= new NorthwindDataContext();
        gridView.DataSource 
= from product in northwind.Products where product.Supplier.Country == "USA" orderby product.ProductName select product;
        gridView.DataBind();
    }
}

请注意这一句:where product.Supplier.Country == "USA"。

至此已经大功告成,运行Default.aspx可以看到结果。整个过程中没有写任何SQL语句来查询数据,甚至没有给出数据库的连接字符串!

可能有的同学会关心查询具体是如何实现的。通过设置断点,可以看到运行时的查询实现:

实现查询的SQL语句为:

{SELECT [t0].[ProductID][t0].[ProductName][t0].[SupplierID][t0].[CategoryID][t0].[QuantityPerUnit][t0].[UnitPrice][t0].[UnitsInStock][t0].[UnitsOnOrder][t0].[ReorderLevel][t0].[Discontinued]
FROM [dbo].[Products] AS [t0]
LEFT OUTER JOIN [dbo].[Suppliers] AS [t1] ON [t1].[SupplierID] = [t0].[SupplierID]
WHERE [t1].[Country] = @p0
ORDER BY [t0].[ProductName]
}

而连接字符串自动加入到了web.config文件中:

<connectionStrings>
    
<add name="NORTHWNDConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NORTHWND.MDF;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient" />
</connectionStrings>

现在网站中的文件如下:

其中Northwind.dbml包含了ORM的映射配置,包括数据库,连接字符串,表,字段,表间关系(比如外键)等的信息:

<?xml version="1.0" encoding="utf-8"?>
<Database Name="NORTHWND" Class="NorthwindDataContext" xmlns="http://schemas.microsoft.com/linqtosql/dbml/2007">
    
<Connection Mode="WebSettings" ConnectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NORTHWND.MDF;Integrated Security=True;User Instance=True" SettingsObjectName="System.Configuration.ConfigurationManager.ConnectionStrings" SettingsPropertyName="NORTHWNDConnectionString" Provider="System.Data.SqlClient" />
    
<Table Name="dbo.Suppliers" Member="Suppliers">
        
<Type Name="Supplier">
            
<Column Name="SupplierID" Type="System.Int32" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" CanBeNull="false" />
            
<Column Name="CompanyName" Type="System.String" DbType="NVarChar(40) NOT NULL" CanBeNull="false" />
            
<Column Name="ContactName" Type="System.String" DbType="NVarChar(30)" CanBeNull="true" />
            
<Column Name="ContactTitle" Type="System.String" DbType="NVarChar(30)" CanBeNull="true" />
            
<Column Name="Address" Type="System.String" DbType="NVarChar(60)" CanBeNull="true" />
            
<Column Name="City" Type="System.String" DbType="NVarChar(15)" CanBeNull="true" />
            
<Column Name="Region" Type="System.String" DbType="NVarChar(15)" CanBeNull="true" />
            
<Column Name="PostalCode" Type="System.String" DbType="NVarChar(10)" CanBeNull="true" />
            
<Column Name="Country" Type="System.String" DbType="NVarChar(15)" CanBeNull="true" />
            
<Column Name="Phone" Type="System.String" DbType="NVarChar(24)" CanBeNull="true" />
            
<Column Name="Fax" Type="System.String" DbType="NVarChar(24)" CanBeNull="true" />
            
<Column Name="HomePage" Type="System.String" DbType="NText" CanBeNull="true" UpdateCheck="Never" />
            
<Association Name="Supplier_Product" Member="Products" OtherKey="SupplierID" Type="Product" />
        
</Type>
    
</Table>
    
<Table Name="dbo.Products" Member="Products">
        
    
</Table>
</Database>

注意<Association>定义了两张表之间的关系。

Northwind.dbml.layout是设计视图的信息。而Northwind.designer.cs包含了为ORM自动生成的一系列object的定义,比如前面用到的和Northwind数据库对应的NorthwindDataContext类,以及和Products表对应的Product类,和Suppliers数据库对应的Supplier类:

#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.1433
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

[System.Data.Linq.Mapping.DatabaseAttribute(Name 
= "NORTHWND")]
public partial class NorthwindDataContext : System.Data.Linq.DataContext
{
    
private static System.Data.Linq.Mapping.MappingSource mappingSource = new AttributeMappingSource();

    
#region Extensibility Method Definitions
    partial 
void OnCreated();
    partial 
void InsertProduct(Product instance);
    partial 
void UpdateProduct(Product instance);
    partial 
void DeleteProduct(Product instance);
    partial 
void InsertSupplier(Supplier instance);
    partial 
void UpdateSupplier(Supplier instance);
    partial 
void DeleteSupplier(Supplier instance);
    
#endregion
    
}

[Table(Name 
= "dbo.Products")]
public partial class Product : INotifyPropertyChanging, INotifyPropertyChanged
{
    
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);

    
private int _ProductID;
    
private string _ProductName;
    
private System.Nullable<int> _SupplierID;
    
private System.Nullable<int> _CategoryID;
    
private string _QuantityPerUnit;
    
private System.Nullable<decimal> _UnitPrice;
    
private System.Nullable<short> _UnitsInStock;
    
private System.Nullable<short> _UnitsOnOrder;
    
private System.Nullable<short> _ReorderLevel;
    
private bool _Discontinued;
    
private EntityRef<Supplier> _Supplier;

    
#region Extensibility Method Definitions
    partial 
void OnLoaded();
    partial 
void OnValidate(System.Data.Linq.ChangeAction action);
    partial 
void OnCreated();
    partial 
void OnProductIDChanging(int value);
    partial 
void OnProductIDChanged();
    partial 
void OnProductNameChanging(string value);
    partial 
void OnProductNameChanged();
    partial 
void OnSupplierIDChanging(System.Nullable<int> value);
    partial 
void OnSupplierIDChanged();
    partial 
void OnCategoryIDChanging(System.Nullable<int> value);
    partial 
void OnCategoryIDChanged();
    partial 
void OnQuantityPerUnitChanging(string value);
    partial 
void OnQuantityPerUnitChanged();
    partial 
void OnUnitPriceChanging(System.Nullable<decimal> value);
    partial 
void OnUnitPriceChanged();
    partial 
void OnUnitsInStockChanging(System.Nullable<short> value);
    partial 
void OnUnitsInStockChanged();
    partial 
void OnUnitsOnOrderChanging(System.Nullable<short> value);
    partial 
void OnUnitsOnOrderChanged();
    partial 
void OnReorderLevelChanging(System.Nullable<short> value);
    partial 
void OnReorderLevelChanged();
    partial 
void OnDiscontinuedChanging(bool value);
    partial 
void OnDiscontinuedChanged();
    
#endregion
    
}

[Table(Name 
= "dbo.Suppliers")]
public partial class Supplier : INotifyPropertyChanging, INotifyPropertyChanged
{
    
}

可以看出,LINQ to SQL提供了一种超酷的方法来实现ORM和数据访问层。用Scott Guthrie的话来说,LINQ很酷的地方在于,LINQ是强类型的。这意味着:

  • 查询会在编译时进行检查,这意味着在开发时就可以检查代码的正确性,而不是像SQL语句,到运行时才会发现错误;
  • 能够在IDE中获得智能感知的提示,这不仅加快了编码速度,而且使复杂的集合和数据源对象模型更容易处理。

注:

Posted on 2007-11-29 09:47 笼民 阅读(570) 评论(0)  编辑 收藏 所属分类: ASP.NETC#

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-11-29 21:37 编辑过


相关链接: