DataContext
DataContext作為LINQ to SQL框架的主入口點,為我們提供了一些方法和屬性,本文用幾個例子說明DataContext幾個典型的應用。
創建和刪除資料庫
CreateDatabase方法用於在伺服器上創建資料庫。
DeleteDatabase方法用於刪除由DataContext連接字串標識的資料庫。
資料庫的名稱有以下方法來定義:
如果資料庫在連接字串中標識,則使用該連接字串的名稱。
如果存在DatabaseAttribute屬性(Attribute),則將其Name屬性(Property)用作資料庫的名稱。
如果連接字串中沒有資料庫標記,並且使用強類型的DataContext,則會檢查與DataContext繼承類名稱相同的資料庫。如果使用弱類型的DataContext,則會引發異常。
如果已通過使用檔案名創建了DataContext,則會創建與該檔案名相對應的資料庫。
我們首先用實體類描述關聯式資料庫表和列的結構的屬性。再調用DataContext的CreateDatabase方法,LINQ to SQL會用我們的定義的實體類結構來構造一個新的資料庫實例。還可以通過使用 .mdf 檔或只使用目錄名(取決於連接字串),將 CreateDatabase與SQL Server一起使用。LINQ to SQL使用連接字串來定義要創建的資料庫和作為資料庫創建位置的伺服器。
說了這麼多,用一段實例說明一下吧!
首先,我們新建一個NewCreateDB類用於創建一個名為NewCreateDB.mdf的新資料庫,該資料庫有一個Person表,有三個欄位,分別為PersonID、PersonName、Age。
public class NewCreateDB : DataContext { public Table Persons; public NewCreateDB(string connection) : base(connection) { } public NewCreateDB(System.Data.IDbConnection connection) : base(connection) { } } [Table(Name = "Person")] public partial class Person : INotifyPropertyChanged { private int _PersonID; private string _PersonName; private System.Nullable _Age; public Person() { } [Column(Storage = "_PersonID", DbType = "INT", IsPrimaryKey = true)] public int PersonID { get { return this._PersonID; } set { if ((this._PersonID != value)) { this.OnPropertyChanged("PersonID"); this._PersonID = value; this.OnPropertyChanged("PersonID"); } } } [Column(Storage = "_PersonName", DbType = "NVarChar(30)")] public string PersonName { get { return this._PersonName; } set { if ((this._PersonName != value)) { this.OnPropertyChanged("PersonName"); this._PersonName = value; this.OnPropertyChanged("PersonName"); } } } [Column(Storage = "_Age", DbType = "INT")] public System.Nullable Age { get { return this._Age; } set { if ((this._Age != value)) { this.OnPropertyChanged("Age"); this._Age = value; this.OnPropertyChanged("Age"); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string PropertyName) { if ((this.PropertyChanged != null)) { this.PropertyChanged(this, new PropertyChangedEventArgs(PropertyName)); } } }
接下來的一段代碼先創建一個資料庫,在調用CreateDatabase後,新的資料庫就會存在並且會接受一般的查詢和命令。接著插入一條記錄並且查詢。最後刪除這個資料庫。
//1.新建一個暫存檔案夾來存放新建的資料庫 string userTempFolder = Environment.GetEnvironmentVariable ("SystemDrive") + @"\YJingLee"; Directory.CreateDirectory(userTempFolder); //2.新建資料庫NewCreateDB string userMDF = System.IO.Path.Combine(userTempFolder, @"NewCreateDB.mdf"); string connStr = String.Format(@"Data Source=.\SQLEXPRESS; AttachDbFilename={0};Integrated Security=True; Connect Timeout=30;User Instance=True; Integrated Security = SSPI;", userMDF); NewCreateDB newDB = new NewCreateDB(connStr); newDB.CreateDatabase(); //3.插入資料並查詢 var newRow = new Person { PersonID = 1, PersonName = "YJingLee", Age = 22 }; newDB.Persons.InsertOnSubmit(newRow); newDB.SubmitChanges(); var q = from x in newDB.Persons select x; //4.刪除資料庫 newDB.DeleteDatabase(); //5.刪除臨時目錄 Directory.Delete(userTempFolder);
資料庫驗證
DatabaseExists方法用於嘗試通過使用DataContext中的連接打開資料庫,如果成功返回true。
下面代碼說明是否存在Northwind資料庫和NewCreateDB資料庫 。
//檢測Northwind資料庫是否存在 if (db.DatabaseExists()) Console.WriteLine("Northwind數據庫存在"); else Console.WriteLine("Northwind資料庫不存在"); //檢測NewCreateDB資料庫是否存在 string userTempFolder = Environment.GetEnvironmentVariable("Temp"); string userMDF = System.IO.Path.Combine(userTempFolder,@"NewCreateDB.mdf"); NewCreateDB newDB = new NewCreateDB(userMDF); if (newDB.DatabaseExists()) Console.WriteLine("NewCreateDB數據庫存在"); else Console.WriteLine("NewCreateDB資料庫不存在");
資料庫更改
SubmitChanges方法計算要插入、更新或刪除的已修改物件的集,並執行相應命令以實現對資料庫的更改。
無論物件做了多少項更改,都只是在更改記憶體中的副本。並未對資料庫中的實際資料做任何更改。直到對DataContext顯式調用SubmitChanges,所做的更改才會傳輸到伺服器。調用時,DataContext會設法將我們所做的更改轉換為等效的SQL命令。我們也可以使用自己的自訂邏輯來重寫這些操作,但提交順序是由DataContext的一項稱作“更改處理器”的服務來協調的。事件的順序如下:
1. 當調用SubmitChanges時,LINQ to SQL會檢查已知物件的集合以確定新實例是否已附加到它們。如果已附加,這些新實例將添加到被跟蹤物件的集合。
2. 所有具有掛起更改的物件將按照它們之間的依賴關係排序成一個物件序列。如果一個物件的更改依賴於其他物件,則這個物件將排在其依賴項之後。
3. 在即將傳輸任何實際更改時,LINQ to SQL會啟動一個事務來封裝由各條命令組成的系列。
4. 對物件的更改會逐個轉換為SQL命令,然後發送到伺服器。
如果資料庫檢測到任何錯誤,都會造成提交進程停止並引發異常。將回滾對資料庫的所有更改,就像未進行過提交一樣。DataContext 仍具有所有更改的完整記錄。
下面代碼說明的是在資料庫中查詢CustomerID為ALFKI的顧客,然後修改其公司名稱,第一次更新並調用SubmitChanges()方法,第二次更新了資料但並未調用SubmitChanges()方法。
//查詢 Customer cust = db.Customers.First(c => c.CustomerID == "ALFKI"); //更新資料並調用SubmitChanges()方法 cust.CompanyName = "YJingLee's Blog"; db.SubmitChanges(); //更新資料沒有調用SubmitChanges()方法 cust.CompanyName = "http://lyj.cnblogs.com";
動態查詢
使用動態查詢,這個例子用CreateQuery()方法創建一個IQueryable<T>類型運算式輸出查詢的語句。這裡給個例子說明一下。有關動態查詢具體內容,下一篇介紹。
var c1 = Expression.Parameter(typeof(Customer), "c"); PropertyInfo City = typeof(Customer).GetProperty("City"); var pred = Expression.Lambda<Func<Customer, bool>>( Expression.Equal( Expression.Property(c1, City), Expression.Constant("Seattle") ), c1); IQueryable custs = db.Customers; Expression expr = Expression.Call(typeof(Queryable), "Where", new Type[] { custs.ElementType }, custs.Expression, pred); IQueryable<Customer> q = db.Customers.AsQueryable(). Provider.CreateQuery<Customer>(expr);
日誌
Log屬性用於將SQL查詢或命令列印到TextReader。此方法對瞭解 LINQ to SQL 功能和調試特定的問題可能很有用。
下面的示例使用Log屬性在SQL代碼執行前在控制台視窗中顯示此代碼。我們可以將此屬性與查詢、插入、更新和刪除命令一起使用。
//關閉日誌功能 //db.Log = null; //使用日誌功能:日誌輸出到控制台視窗 db.Log = Console.Out; var q = from c in db.Customers where c.City == "London" select c; //日誌輸出到檔 StreamWriter sw = new StreamWriter(Server.MapPath("log.txt"), true); db.Log = sw; var q = from c in db.Customers where c.City == "London" select c; sw.Close();
留言列表