程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 學Linq to sql(二):DataContext與實體

學Linq to sql(二):DataContext與實體

編輯:關於.NET

DataContext

DataContext類型(數據上下文)是System.Data.Linq命名空間下的重要類型,用於把查詢句法翻譯成SQL語句,以及把數據從數據庫返回給調用方和把實體的修改寫入數據庫。

DataContext提供了以下一些使用的功能:

l 以日志形式記錄DataContext生成的SQl 

l 執行SQl (包括查詢和更新語句)

l 創建和刪除數據庫

DataContext是實體和數據庫之間的橋梁,那麼首先我們需要定義映射到數據表的實體。

定義實體類

using System.Data.Linq.Mapping;

[Table(Name = "Customers")]
public class Customer
{
  [Column(IsPrimaryKey = true)]
  public string CustomerID {get; set;}

  [Column(Name = "ContactName")]
  public string Name { get; set; }

  [Column]
  public string City {get; set;}
}

以Northwind數據庫為例,上述Customers類被映射成一個表,對應數據庫中的 Customers表。然後在類型中定義了三個屬性,對應表中的三個字段。其中,CustomerID字段是主鍵,如果沒有指定Column特性的Name屬性,那麼系統會把屬性名作為數據表的字段名,也就是說實體類的屬性名就需要和數據表中的字段名一致。

現在,創建一個ASP.NET頁面,然後在頁面上加入一個GridView控件,使用下面的代碼進行綁定數據:

using System.Data.Linq;

DataContext ctx = new DataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
Table<Customer> Customers = ctx.GetTable<Customer>();
GridView1.DataSource = from c in Customers where c.CustomerID.StartsWith("A") select new {顧客ID=c.CustomerID, 顧客名=c.Name, 城市=c.City};
GridView1.DataBind();

使用DataContext類型把實體類和數據庫中的數據進行關聯。你可以直接在DataContext的構造方法中定義連接字符串,也可以使用IDbConnection:

using System.Data.SqlClient;

IDbConnection conn = new SqlConnection("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
DataContext ctx = new DataContext(conn);

之後,通過GetTable獲取表示底層數據表的Table類型,顯然,數據庫中的Customers表的實體是Customer類型。隨後的查詢句法,即使你不懂SQL應該也能看明白。從Customers表中找出CustomerID以“A”開頭的記錄,並把CustomersID、Name以及City封裝成新的匿名類型進行返回。

結果如下圖:

強類型DataContext

public partial class NorthwindDataContext : DataContext
{
  public Table<Customer> Customers;
  public NorthwindDataContext(IDbConnection connection) : base(connection) { }
  public NorthwindDataContext(string connection) : base(connection) { }
}

強類型數據上下文使代碼更簡潔:

NorthwindDataContext ctx = new NorthwindDataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
GridView1.DataSource = from c in ctx.Customers where c.CustomerID.StartsWith("A") select new { 顧客ID = c.CustomerID, 顧客名 = c.Name, 城市 = c.City };
GridView1.DataBind();

DataContext其實封裝了很多實用的功能,下面一一介紹。

日志功能

using System.IO;

NorthwindDataContext ctx = new NorthwindDataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
StreamWriter sw = new StreamWriter(Server.MapPath("log.txt"), true); // Append
ctx.Log = sw;
GridView1.DataSource = from c in ctx.Customers where c.CustomerID.StartsWith("A") select new { 顧客ID = c.CustomerID, 顧客名 = c.Name, 城市 = c.City };
GridView1.DataBind();
sw.Close();

運行程序後在網站所在目錄生成了log.txt,每次查詢都會把諸如下面的日志追加到文本文件中:

SELECT [t0].[CustomerID], [t0].[ContactName], [t0].[City]
FROM [Customers] AS [t0]
WHERE [t0].[CustomerID] LIKE @p0
-- @p0: Input String (Size = 2; Prec = 0; Scale = 0) [A%]
-- Context: SqlProvider(Sql2005) Model : AttributedMetaModel Build: 3.5.20706.1

應該說這樣的日志對於調試程序是非常有幫助的。

探究查詢

using System.Data.Common;
using System.Collections.Generic;

NorthwindDataContext ctx = new NorthwindDataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
var select = from c in ctx.Customers where c.CustomerID.StartsWith("A") select new { 顧客ID = c.CustomerID, 顧客名 = c.Name, 城市 = c.City };
DbCommand cmd = ctx.GetCommand(select);
Response.Write(cmd.CommandText + "<br/>");
foreach (DbParameter parm in cmd.Parameters)
  Response.Write(string.Format("參數名:{0},參數值:{1}<br/>", parm.ParameterName, parm.Value));
Customer customer = ctx.Customers.First();
customer.Name = "zhuye";
IList<object> queryText = ctx.GetChangeSet().ModifiedEntities;
Response.Write(((Customer)queryText[0]).Name);

在這裡,我們通過DataContext的GetCommand方法獲取了查詢對應的DbCommand,並且輸出了CommandText和所有的DbParameter。之後,我們又通過GetChangeSet方法獲取了修改後的實體,並輸出了修改內容。

執行查詢

NorthwindDataContext ctx = new NorthwindDataContext("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
string newcity = "Shanghai";
ctx.ExecuteCommand("update Customers set City={0} where CustomerID like 'A%'", newcity);
IEnumerable<Customer> customers = ctx.ExecuteQuery<Customer>("select * from Customers where CustomerID like 'A%'");
GridView1.DataSource = customers;
GridView1.DataBind();

前一篇文章已經說了,雖然Linq to sql能實現90%以上的TSQL功能。但是不可否認,對於復雜的查詢,使用TSQL能獲得更好的效率。因此,DataContext類型也提供了執行SQL語句的能力。代碼的執行結果如下圖:

創建數據庫

testContext ctx = new testContext("server=xxx;database=testdb;uid=xxx;pwd=xxx");
ctx.CreateDatabase();

[Table(Name = "test")]
public class test
{
  [Column(IsPrimaryKey = true, IsDbGenerated = true)]
  public int ID { get; set; }

  [Column(DbType="varchar(20)")]
  public string Name { get; set; }
}

public partial class testContext : DataContext
{
  public Table<test> test;
  public testContext(string connection) : base(connection) { }
}

這段代碼在數據庫中創建了名為testdb的數據庫,等同於下面的腳本:

CREATE TABLE [dbo].[test](
  [ID] [int] IDENTITY(1,1) NOT NULl ,
  [Name] [varchar](20) COLLATE Chinese_PRC_CI_AS NULl ,
CONSTRAINT [PK_test] PRIMARY KEY CLUSTERED
(
  [ID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

同時,DataContext還提供了DeleteDatabase()方法,在這裡就不列舉了。

使用DbDataReader數據源

using System.Data.SqlClient;

var conn = new SqlConnection("server=xxx;database=Northwind;uid=xxx;pwd=xxx");
var ctx = new DataContext(conn);
var cmd = new SqlCommand("select * from customers where CustomerID like 'A%'", conn);
conn.Open();
var reader = cmd.ExecuteReader();
GridView1.DataSource = ctx.Translate<Customer>(reader);
GridView1.DataBind();
conn.Close();

你同樣可以選擇使用DataReader獲取數據,增加了靈活性的同時也增加了性能。

看到這裡,你可能會覺得手工定義和數據庫中表對應的實體類很麻煩,不用擔心,VS2008提供了自動生成實體類以及關系的工具,工具的使用將在以後講解。今天就講到這裡,和DataContext相關的事務、加載選項、並發選項以及關系實體等高級內容也將在以後講解。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved