C#數(shù)據(jù)庫(kù)操作之LINQ to SQL技術(shù)詳解
一、LINQ to SQL技術(shù)概述
LINQ to SQL 是 .NET Framework version 3.5 的一個(gè)組件,提供了用于將關(guān)系數(shù)據(jù)作為對(duì)象管理的運(yùn)行時(shí)基礎(chǔ)結(jié)構(gòu)。
在 LINQ to SQL 中,將關(guān)系數(shù)據(jù)庫(kù)的數(shù)據(jù)模型,映射到一種對(duì)象模型中,該對(duì)象模型省指開(kāi)發(fā)人員使用的編程語(yǔ)言表示的對(duì)象。通俗來(lái)講,就是將數(shù)據(jù)庫(kù)中的關(guān)系型數(shù)據(jù),映射到代碼里的實(shí)例對(duì)象。 當(dāng)應(yīng)用程序運(yùn)行時(shí),LINQ to SQL 會(huì)將對(duì)象模型中的語(yǔ)言集成查詢(xún)轉(zhuǎn)換為 SQL語(yǔ)句,然后將它們發(fā)送到數(shù)據(jù)庫(kù)進(jìn)行執(zhí)行。 當(dāng)數(shù)據(jù)庫(kù)返回結(jié)果時(shí),LINQ to SQL 會(huì)將它們轉(zhuǎn)換回你可以用你自己的編程語(yǔ)言處理的對(duì)象。
【tips】使用Visual Studio的開(kāi)發(fā)者可以使用對(duì)象關(guān)系設(shè)計(jì)器the Object Relational Designer,它為實(shí)現(xiàn)LINQ to SQL的許多特性提供了一個(gè)用戶(hù)界面。
二、使用LINQ to SQL 進(jìn)行簡(jiǎn)單操作.
通過(guò)使用 LINQ to SQL,使得訪(fǎng)問(wèn) SQL 數(shù)據(jù)庫(kù),就像訪(fǎng)問(wèn)內(nèi)存中的集合一樣。
以下代碼,創(chuàng)建一個(gè)Northwnd對(duì)象,代表northwnd數(shù)據(jù)庫(kù),并從Customers表中查詢(xún)出城市為“London”的數(shù)據(jù),返回一個(gè)集合,賦值給companyNameQuery,之后通過(guò)循環(huán),輸出集合內(nèi)的元素。
// Northwnd inherits from System.Data.Linq.DataContext. Northwnd nw = new Northwnd(@"northwnd.mdf"); // or, if you are not using SQL Server Express // Northwnd nw = new Northwnd("Database=Northwind;Server=server_name;Integrated Security=SSPI"); var companyNameQuery = from cust in nw.Customers where cust.City == "London" select cust.CompanyName; foreach (var customer in companyNameQuery) { Console.WriteLine(customer); }
通過(guò)上述例子中,相必您已經(jīng)體會(huì)到了LINQ to SQL技術(shù)的強(qiáng)大之處了,接下來(lái),我將帶領(lǐng)你們逐步的吸收LINQ to SQL技術(shù)。
三、如何動(dòng)態(tài)創(chuàng)建數(shù)據(jù)庫(kù)
在LINQ to SQL技術(shù)中,對(duì)象模型和關(guān)系型數(shù)據(jù)庫(kù)之間是映射關(guān)系。要想啟用映射關(guān)系,一般可以通過(guò)使用基于特性的映射,或者是使用描述關(guān)系數(shù)據(jù)庫(kù)結(jié)構(gòu)的外部映射文件。在這兩種情況下,如果你有足夠的關(guān)系型數(shù)據(jù)庫(kù)的信息,那么就可以通過(guò)使用DataContext.CreateDatabase()方法來(lái)創(chuàng)建數(shù)據(jù)庫(kù)實(shí)例。
DataContext.CreateDatabase()方法,僅在對(duì)象模型中被編碼信息的范圍內(nèi)創(chuàng)建數(shù)據(jù)庫(kù)的副本。對(duì)象模型中的映射文件和特性,不會(huì)對(duì)現(xiàn)有數(shù)據(jù)庫(kù)結(jié)構(gòu)的所有內(nèi)容進(jìn)行編碼。映射信息不表示用戶(hù)自定義函數(shù)、存儲(chǔ)過(guò)程、觸發(fā)器或檢查約束的內(nèi)容。這種行為對(duì)于各種數(shù)據(jù)庫(kù)來(lái)說(shuō)已經(jīng)足夠了。
如果已知的數(shù)據(jù)提供者是可用的(如SQL Server 2008),那么你可以在任何情況下使用DataContext.CreateDatabase()方法。
- →構(gòu)建一個(gè)自動(dòng)安裝在客戶(hù)系統(tǒng)上的應(yīng)用程序。
- →構(gòu)建一個(gè)客戶(hù)機(jī)應(yīng)用程序,該應(yīng)用程序需要一個(gè)本地?cái)?shù)據(jù)庫(kù)來(lái)保存其脫機(jī)狀態(tài)。
您還可以使用DataContext.CreateDatabase()方法來(lái)使用SQL Server,通過(guò)創(chuàng)建.mdf文件或目錄名,具體是哪種取決于您的連接字符串。LINQ to SQL 使用連接字符串來(lái)定義將要?jiǎng)?chuàng)建的數(shù)據(jù)庫(kù),以及要?jiǎng)?chuàng)建數(shù)據(jù)連接的服務(wù)器。
【tips】盡可能的,請(qǐng)使用Windows集成安全性連接到數(shù)據(jù)庫(kù),以便在連接字符串中不需要密碼。
案例一:
該例展示了一個(gè)如何創(chuàng)建一個(gè)名為MyDVDs.mdf數(shù)據(jù)庫(kù)的方式。
//在使用該例展示的方法之前,必須進(jìn)行以下兩個(gè)步驟: //1、添加引用System.Data.Linq; //2、使用using語(yǔ)句,添加命名空間,否則報(bào)錯(cuò) // using TableAttribute = System.Data.Linq.Mapping.TableAttribute; // using ColumnAttribute = System.Data.Linq.Mapping.ColumnAttribute; //Table特性,創(chuàng)建了數(shù)據(jù)庫(kù)中的名為DVDTable的表與該類(lèi)之間的映射關(guān)系。 [Table(Name = "MyOrders")] public class Order { //Column特性,創(chuàng)建了DVDTable表中同名列與該類(lèi)成員屬性之間的映射關(guān)系。 [Column(IsPrimaryKey = true)] public int id; [Column] public string name; [Column] public DateTime date; public override string ToString() { return "Order對(duì)象:{" + id + "," + name + "," + date + "}"; } } //自定義類(lèi) ,繼承DataContext類(lèi)。 public class MyOrders : DataContext { public MyOrders(String connection) : base(connection) { } public Table<Order> orders; } //創(chuàng)建一個(gè)MyOrders 類(lèi)的對(duì)象db,該類(lèi)繼承自DataContext類(lèi)。 MyOrders myOrders = new MyOrders(@"D:\myFirstOrder.mdf"); public void CreateDatabase() { if (myOrders.DatabaseExists()) { //先判斷該路徑中,是否存在該數(shù)據(jù)庫(kù)文件,如果存在,則刪除。 MessageBox.Show("Deleting old database..."); myOrders.DeleteDatabase(); } //myOrders對(duì)象創(chuàng)建數(shù)據(jù)庫(kù) myOrders.CreateDatabase(); //釋放DataContext實(shí)例,所使用的的所有資源 //myOrders.Dispose(); }
【注意】
MyOrders myOrders = new MyOrders(@"D:\myFirstOrder4.mdf");
語(yǔ)句中的myOrders對(duì)象,最好設(shè)置成全局變量,如果設(shè)置成局部變量,后續(xù)在重復(fù)的調(diào)用方法時(shí),可能會(huì)出現(xiàn)“該數(shù)據(jù)庫(kù)已存在,請(qǐng)選擇其他數(shù)據(jù)庫(kù)名稱(chēng)”異常。
在構(gòu)建自動(dòng)安裝在客戶(hù)系統(tǒng)上的應(yīng)用程序時(shí),請(qǐng)先查看數(shù)據(jù)庫(kù)是否已經(jīng)存在,并在創(chuàng)建新數(shù)據(jù)庫(kù)之前刪除它。DataContext類(lèi)提供DatabaseExists()和DeleteDatabase()方法來(lái)幫助您完成這個(gè)過(guò)程。
四、如何向數(shù)據(jù)庫(kù)中insert數(shù)據(jù)
通過(guò)向關(guān)聯(lián)的LINQ to SQL里的Table<TEntity>集合添加對(duì)象,然后向數(shù)據(jù)庫(kù)提交更改,您就可以將行插入到數(shù)據(jù)庫(kù)中。LINK to SQL將您提交的更改,翻譯成適當(dāng)?shù)腟QL insert語(yǔ)句,然后提交到數(shù)據(jù)庫(kù)執(zhí)行的。
【tips】您也可以為L(zhǎng)INQ to SQL里默認(rèn)的insert數(shù)據(jù)庫(kù)、Update數(shù)據(jù)庫(kù)、Delete數(shù)據(jù)庫(kù)等操作進(jìn)行重載。
以下步驟假設(shè)有一個(gè)連接到Northwind數(shù)據(jù)庫(kù)的DataContext連接。
- 1、創(chuàng)建一個(gè)新對(duì)象,包含要提交的列數(shù)據(jù)。
- 2、將新對(duì)象添加到與數(shù)據(jù)庫(kù)中目標(biāo)表相關(guān)聯(lián)的LINQ to SQL Table集合中。
- 3、提交更改到數(shù)據(jù)庫(kù)中。
下面代碼展示了創(chuàng)建一個(gè)新的Order對(duì)象(Order是用戶(hù)自定義類(lèi)),然后為它填充適當(dāng)?shù)膶傩灾?。之后將新的Order對(duì)象添加到Order集合里。最后,將更改提交到數(shù)據(jù)庫(kù),作為Orders表中一個(gè)新的行。
// Create a new Order object.Order class is user defined class. Order ord = new Order { id = 12000, name = "Harry Potty", OrderDate = DateTime.Now // … }; // Add the new object to the Orders collection. System.Data.Linq.Table<Order> table = myOrders.GetTable<Order>(); table.InsertOnSubmit(ord); // Submit the change to the database. try { myOrders.SubmitChanges(); } catch (Exception e) { MessageBox.Show(e.Message); // Make some adjustments. // ... // Try again. myOrders.SubmitChanges(); } //釋放資源 //myOrders.Dispose();
【注意】在向數(shù)據(jù)庫(kù)中的表里,insert數(shù)據(jù)或者后續(xù)的update、delete操作時(shí),無(wú)論您對(duì)對(duì)象做了多少項(xiàng)更改,都只是在更改內(nèi)存中的副本。 您并未對(duì)數(shù)據(jù)庫(kù)中的實(shí)際數(shù)據(jù)做任何更改。 直到您對(duì) 顯式調(diào)用DataContext里的SubmitChanges()方法 ,您所做的更改才會(huì)傳輸?shù)椒?wù)器。
五、如何從數(shù)據(jù)庫(kù)中query數(shù)據(jù)
LINQ to SQL 中的查詢(xún)使用與 LINQ 中的查詢(xún)相同的語(yǔ)法。 唯一的差異是 LINQ to SQL 查詢(xún)中引用的對(duì)象映射到數(shù)據(jù)庫(kù)中的元素。 有興趣的朋友,可以看下 LINQ 查詢(xún)知識(shí)。
下面的代碼,展示了一個(gè)簡(jiǎn)單的查詢(xún)請(qǐng)求,查詢(xún)出id等于12000的訂單,并將查詢(xún)結(jié)果輸出。
MyOrders myOrders = new MyOrders(@"c:\northwnd.mdf"); System.Data.Linq.Table<Order> table = myOrders.GetTable<Order>(); // Query for customers in London. IQueryable<Customer> custQuery = from order in myOrders.orders where order.id == 12000 select order; //將查詢(xún)結(jié)果輸出 foreach( var o in result) { Console.WriteLine(o.toString()); }
從數(shù)據(jù)庫(kù)中查詢(xún)數(shù)據(jù),還有更多復(fù)雜的操作,后續(xù)我會(huì)繼續(xù)整理更為詳細(xì)的數(shù)據(jù)庫(kù)查詢(xún)操作,可以先關(guān)注下。
六、如何update表中的數(shù)據(jù)
通過(guò)修改與LINQ to SQL 的Table集合相關(guān)聯(lián)的對(duì)象的成員值,然后將更改提交給數(shù)據(jù)庫(kù),那么就可以更新數(shù)據(jù)庫(kù)中的某行數(shù)據(jù)。LINQ to SQL 將你的改變轉(zhuǎn)換為相對(duì)應(yīng)的SQL update語(yǔ)句。
將某行數(shù)據(jù)更新到數(shù)據(jù)庫(kù)中的步驟如下:
1、在數(shù)據(jù)庫(kù)中查詢(xún)要更新的行。
2、對(duì)第1步的LINQ to SQL 查詢(xún)結(jié)果里的成員值進(jìn)行所需的更改。
3、將更改提交到數(shù)據(jù)庫(kù)里。
下面的示例在數(shù)據(jù)庫(kù)中查詢(xún)訂單#11000,然后更改結(jié)果order對(duì)象中的name和date的值。最后,對(duì)這些成員值的更改作為name和date列中的更改提交給數(shù)據(jù)庫(kù)。
// Query the database for the row to be updated. var query = from ord in myOrders.Orders where ord.id== 11000 select ord; // Execute the query, and change the column values // you want to change. foreach (Order ord in query) { ord.name = "Hong Lou Meng"; ord.date = DateTime.Now; // Insert any additional changes to column values. } // Submit the changes to the database. try { myOrders.SubmitChanges(); } catch (Exception e) { MessageBox.Show(Console.WriteLine(e)); // Provide for exceptions. } //釋放DataContext對(duì)象占用的資源。 //myOrders.Dispose();
七、如何如何delete表中的數(shù)據(jù)
可以通過(guò)從與表相關(guān)聯(lián)的集合中刪除相應(yīng)的LINQ to SQL對(duì)象,來(lái)完成對(duì)數(shù)據(jù)庫(kù)中某行的刪除。LINQ to SQL 會(huì)將刪除操作轉(zhuǎn)變?yōu)檫m當(dāng)?shù)腟QL delete語(yǔ)句。
LINQ to SQL不支持或不識(shí)別級(jí)聯(lián)刪除操作。如果你想刪除表中有約束的一行,你必須完成以下其中一項(xiàng)條件:
1、在數(shù)據(jù)庫(kù)的外鍵約束中設(shè)置ON DELETE CASCADE規(guī)則。
2、使用您自己的代碼先刪除阻止父對(duì)象被刪除的子對(duì)象。
如果無(wú)法保證上述至少一個(gè)條件成立,則將拋出異常。請(qǐng)參閱本主題的第二個(gè)代碼示例。
刪除數(shù)據(jù)庫(kù)中某一行的操作如下:
- 1、在數(shù)據(jù)庫(kù)中查詢(xún)需要?jiǎng)h除的行。
- 2、調(diào)用DeleteOnSubmit方法。
- 3、將刪除操作提交到數(shù)據(jù)庫(kù)。
下面的第1個(gè)代碼示例向數(shù)據(jù)庫(kù)查詢(xún)屬于order# 11000的訂單詳細(xì)信息,將這些訂單詳細(xì)信息標(biāo)記為刪除,并將這些更改提交給數(shù)據(jù)庫(kù)。
Table<Order> orders = myOrders.GetTable<Order>(); // Query the database for the rows to be deleted. var deleteResult = from ord in orders where ord.id == 11000 select ord; foreach (var ord in deleteResult ) { orders.DeleteOnSubmit(ord ); } try { myOrders.SubmitChanges(); } catch (Exception e) { MessagBox.Show(e.Message); // Provide for exceptions. }
在第二個(gè)代碼示例中,目標(biāo)是刪除一個(gè)訂單(#10250)。代碼首先檢查OrderDetails表,以查看要?jiǎng)h除的訂單在那里是否有子訂單。如果訂單有子訂單,則首先將子訂單標(biāo)記為要?jiǎng)h除,然后將訂單標(biāo)記為要?jiǎng)h除。DataContext將實(shí)際的刪除按正確的順序排列,以便發(fā)送到數(shù)據(jù)庫(kù)的刪除命令遵守?cái)?shù)據(jù)庫(kù)約束。
//Northwnd myOrders = new Northwnd(@"c:\northwnd.mdf"); MyOrders myOrders = new MyOrders(@"D:\myFirstOrder.mdf"); myOrders.Log = Console.Out; // Specify order to be removed from database int reqOrder = 10250; // Fetch OrderDetails for requested order. var ordDetailQuery = from odq in myOrders.OrderDetails where odq.OrderID == reqOrder select odq; foreach (var selectedDetail in ordDetailQuery) { MessageBox.Show(selectedDetail.toString()); myOrders.OrderDetails.DeleteOnSubmit(selectedDetail); } // Display progress. MessageBox.Show("detail section finished."); // Determine from Detail collection whether parent exists. if (ordDetailQuery.Any()) { MessageBox.Show("The parent is present in the Orders collection."); // Fetch Order. try { var ordFetch = (from ofetch in myOrders.Orders where ofetch.OrderID == reqOrder select ofetch).First(); myOrders.Orders.DeleteOnSubmit(ordFetch); MessageBox.Show("{0} OrderID is marked for deletion.", ordFetch.OrderID); } catch (Exception e) { MessageBox.Show(e.Message); } } else { MessageBox.Show("There was no parent in the Orders collection."); } // Display progress. MessageBox.Show("Order section finished."); try { myOrders.SubmitChanges(); } catch (Exception e) { MessageBox.Show(e.Message); } // Display progress. MessageBox.Show("Submit finished.");
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C#實(shí)現(xiàn)窗體抖動(dòng)的兩種方法
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)窗體抖動(dòng)的兩種方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11C#中Thread(線(xiàn)程)和Task(任務(wù))實(shí)例詳解
.NET Framework在System.Threading命名空間中具有與線(xiàn)程相關(guān)的類(lèi),線(xiàn)程是一小組可執(zhí)行指令,這篇文章主要給大家介紹了關(guān)于C#中Thread(線(xiàn)程)和Task(任務(wù))的相關(guān)資料,需要的朋友可以參考下2022-03-03C# 修改文件的創(chuàng)建、修改和訪(fǎng)問(wèn)時(shí)間的示例
這篇文章主要介紹了C#實(shí)現(xiàn)修改文件的創(chuàng)建、修改和訪(fǎng)問(wèn)時(shí)間的示例,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-04-04基于C#實(shí)現(xiàn)的屏幕指定區(qū)域截屏代碼
這篇文章主要介紹了C#實(shí)現(xiàn)的屏幕指定區(qū)域截屏代碼,有需要的朋友可以參考一下2014-01-01C#實(shí)現(xiàn)文件讀寫(xiě)到SQLite數(shù)據(jù)庫(kù)
這篇文章主要為大家詳細(xì)介紹了使用?C#?將文件讀寫(xiě)到?SQLite?數(shù)據(jù)庫(kù)的幾種方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2025-01-01TextBox獲取輸入焦點(diǎn)時(shí)自動(dòng)全選的實(shí)現(xiàn)方法
TextBox獲取輸入焦點(diǎn)時(shí)自動(dòng)全選的實(shí)現(xiàn)方法,需要的朋友可以參考一下2013-03-03