C#數(shù)據(jù)庫操作之LINQ to SQL技術(shù)詳解
一、LINQ to SQL技術(shù)概述
LINQ to SQL 是 .NET Framework version 3.5 的一個組件,提供了用于將關(guān)系數(shù)據(jù)作為對象管理的運行時基礎(chǔ)結(jié)構(gòu)。
在 LINQ to SQL 中,將關(guān)系數(shù)據(jù)庫的數(shù)據(jù)模型,映射到一種對象模型中,該對象模型省指開發(fā)人員使用的編程語言表示的對象。通俗來講,就是將數(shù)據(jù)庫中的關(guān)系型數(shù)據(jù),映射到代碼里的實例對象。 當應(yīng)用程序運行時,LINQ to SQL 會將對象模型中的語言集成查詢轉(zhuǎn)換為 SQL語句,然后將它們發(fā)送到數(shù)據(jù)庫進行執(zhí)行。 當數(shù)據(jù)庫返回結(jié)果時,LINQ to SQL 會將它們轉(zhuǎn)換回你可以用你自己的編程語言處理的對象。
【tips】使用Visual Studio的開發(fā)者可以使用對象關(guān)系設(shè)計器the Object Relational Designer,它為實現(xiàn)LINQ to SQL的許多特性提供了一個用戶界面。
二、使用LINQ to SQL 進行簡單操作.
通過使用 LINQ to SQL,使得訪問 SQL 數(shù)據(jù)庫,就像訪問內(nèi)存中的集合一樣。
以下代碼,創(chuàng)建一個Northwnd對象,代表northwnd數(shù)據(jù)庫,并從Customers表中查詢出城市為“London”的數(shù)據(jù),返回一個集合,賦值給companyNameQuery,之后通過循環(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); }
通過上述例子中,相必您已經(jīng)體會到了LINQ to SQL技術(shù)的強大之處了,接下來,我將帶領(lǐng)你們逐步的吸收LINQ to SQL技術(shù)。
三、如何動態(tài)創(chuàng)建數(shù)據(jù)庫
在LINQ to SQL技術(shù)中,對象模型和關(guān)系型數(shù)據(jù)庫之間是映射關(guān)系。要想啟用映射關(guān)系,一般可以通過使用基于特性的映射,或者是使用描述關(guān)系數(shù)據(jù)庫結(jié)構(gòu)的外部映射文件。在這兩種情況下,如果你有足夠的關(guān)系型數(shù)據(jù)庫的信息,那么就可以通過使用DataContext.CreateDatabase()方法來創(chuàng)建數(shù)據(jù)庫實例。
DataContext.CreateDatabase()方法,僅在對象模型中被編碼信息的范圍內(nèi)創(chuàng)建數(shù)據(jù)庫的副本。對象模型中的映射文件和特性,不會對現(xiàn)有數(shù)據(jù)庫結(jié)構(gòu)的所有內(nèi)容進行編碼。映射信息不表示用戶自定義函數(shù)、存儲過程、觸發(fā)器或檢查約束的內(nèi)容。這種行為對于各種數(shù)據(jù)庫來說已經(jīng)足夠了。
如果已知的數(shù)據(jù)提供者是可用的(如SQL Server 2008),那么你可以在任何情況下使用DataContext.CreateDatabase()方法。
- →構(gòu)建一個自動安裝在客戶系統(tǒng)上的應(yīng)用程序。
- →構(gòu)建一個客戶機應(yīng)用程序,該應(yīng)用程序需要一個本地數(shù)據(jù)庫來保存其脫機狀態(tài)。
您還可以使用DataContext.CreateDatabase()方法來使用SQL Server,通過創(chuàng)建.mdf文件或目錄名,具體是哪種取決于您的連接字符串。LINQ to SQL 使用連接字符串來定義將要創(chuàng)建的數(shù)據(jù)庫,以及要創(chuàng)建數(shù)據(jù)連接的服務(wù)器。
【tips】盡可能的,請使用Windows集成安全性連接到數(shù)據(jù)庫,以便在連接字符串中不需要密碼。
案例一:
該例展示了一個如何創(chuàng)建一個名為MyDVDs.mdf數(shù)據(jù)庫的方式。
//在使用該例展示的方法之前,必須進行以下兩個步驟: //1、添加引用System.Data.Linq; //2、使用using語句,添加命名空間,否則報錯 // using TableAttribute = System.Data.Linq.Mapping.TableAttribute; // using ColumnAttribute = System.Data.Linq.Mapping.ColumnAttribute; //Table特性,創(chuàng)建了數(shù)據(jù)庫中的名為DVDTable的表與該類之間的映射關(guān)系。 [Table(Name = "MyOrders")] public class Order { //Column特性,創(chuàng)建了DVDTable表中同名列與該類成員屬性之間的映射關(guān)系。 [Column(IsPrimaryKey = true)] public int id; [Column] public string name; [Column] public DateTime date; public override string ToString() { return "Order對象:{" + id + "," + name + "," + date + "}"; } } //自定義類 ,繼承DataContext類。 public class MyOrders : DataContext { public MyOrders(String connection) : base(connection) { } public Table<Order> orders; } //創(chuàng)建一個MyOrders 類的對象db,該類繼承自DataContext類。 MyOrders myOrders = new MyOrders(@"D:\myFirstOrder.mdf"); public void CreateDatabase() { if (myOrders.DatabaseExists()) { //先判斷該路徑中,是否存在該數(shù)據(jù)庫文件,如果存在,則刪除。 MessageBox.Show("Deleting old database..."); myOrders.DeleteDatabase(); } //myOrders對象創(chuàng)建數(shù)據(jù)庫 myOrders.CreateDatabase(); //釋放DataContext實例,所使用的的所有資源 //myOrders.Dispose(); }
【注意】
MyOrders myOrders = new MyOrders(@"D:\myFirstOrder4.mdf");
語句中的myOrders對象,最好設(shè)置成全局變量,如果設(shè)置成局部變量,后續(xù)在重復(fù)的調(diào)用方法時,可能會出現(xiàn)“該數(shù)據(jù)庫已存在,請選擇其他數(shù)據(jù)庫名稱”異常。
在構(gòu)建自動安裝在客戶系統(tǒng)上的應(yīng)用程序時,請先查看數(shù)據(jù)庫是否已經(jīng)存在,并在創(chuàng)建新數(shù)據(jù)庫之前刪除它。DataContext類提供DatabaseExists()和DeleteDatabase()方法來幫助您完成這個過程。
四、如何向數(shù)據(jù)庫中insert數(shù)據(jù)
通過向關(guān)聯(lián)的LINQ to SQL里的Table<TEntity>集合添加對象,然后向數(shù)據(jù)庫提交更改,您就可以將行插入到數(shù)據(jù)庫中。LINK to SQL將您提交的更改,翻譯成適當?shù)腟QL insert語句,然后提交到數(shù)據(jù)庫執(zhí)行的。
【tips】您也可以為LINQ to SQL里默認的insert數(shù)據(jù)庫、Update數(shù)據(jù)庫、Delete數(shù)據(jù)庫等操作進行重載。
以下步驟假設(shè)有一個連接到Northwind數(shù)據(jù)庫的DataContext連接。
- 1、創(chuàng)建一個新對象,包含要提交的列數(shù)據(jù)。
- 2、將新對象添加到與數(shù)據(jù)庫中目標表相關(guān)聯(lián)的LINQ to SQL Table集合中。
- 3、提交更改到數(shù)據(jù)庫中。
下面代碼展示了創(chuàng)建一個新的Order對象(Order是用戶自定義類),然后為它填充適當?shù)膶傩灾怠V髮⑿碌腛rder對象添加到Order集合里。最后,將更改提交到數(shù)據(jù)庫,作為Orders表中一個新的行。
// 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ù)庫中的表里,insert數(shù)據(jù)或者后續(xù)的update、delete操作時,無論您對對象做了多少項更改,都只是在更改內(nèi)存中的副本。 您并未對數(shù)據(jù)庫中的實際數(shù)據(jù)做任何更改。 直到您對 顯式調(diào)用DataContext里的SubmitChanges()方法 ,您所做的更改才會傳輸?shù)椒?wù)器。
五、如何從數(shù)據(jù)庫中query數(shù)據(jù)
LINQ to SQL 中的查詢使用與 LINQ 中的查詢相同的語法。 唯一的差異是 LINQ to SQL 查詢中引用的對象映射到數(shù)據(jù)庫中的元素。 有興趣的朋友,可以看下 LINQ 查詢知識。
下面的代碼,展示了一個簡單的查詢請求,查詢出id等于12000的訂單,并將查詢結(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; //將查詢結(jié)果輸出 foreach( var o in result) { Console.WriteLine(o.toString()); }
從數(shù)據(jù)庫中查詢數(shù)據(jù),還有更多復(fù)雜的操作,后續(xù)我會繼續(xù)整理更為詳細的數(shù)據(jù)庫查詢操作,可以先關(guān)注下。
六、如何update表中的數(shù)據(jù)
通過修改與LINQ to SQL 的Table集合相關(guān)聯(lián)的對象的成員值,然后將更改提交給數(shù)據(jù)庫,那么就可以更新數(shù)據(jù)庫中的某行數(shù)據(jù)。LINQ to SQL 將你的改變轉(zhuǎn)換為相對應(yīng)的SQL update語句。
將某行數(shù)據(jù)更新到數(shù)據(jù)庫中的步驟如下:
1、在數(shù)據(jù)庫中查詢要更新的行。
2、對第1步的LINQ to SQL 查詢結(jié)果里的成員值進行所需的更改。
3、將更改提交到數(shù)據(jù)庫里。
下面的示例在數(shù)據(jù)庫中查詢訂單#11000,然后更改結(jié)果order對象中的name和date的值。最后,對這些成員值的更改作為name和date列中的更改提交給數(shù)據(jù)庫。
// 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對象占用的資源。 //myOrders.Dispose();
七、如何如何delete表中的數(shù)據(jù)
可以通過從與表相關(guān)聯(lián)的集合中刪除相應(yīng)的LINQ to SQL對象,來完成對數(shù)據(jù)庫中某行的刪除。LINQ to SQL 會將刪除操作轉(zhuǎn)變?yōu)檫m當?shù)腟QL delete語句。
LINQ to SQL不支持或不識別級聯(lián)刪除操作。如果你想刪除表中有約束的一行,你必須完成以下其中一項條件:
1、在數(shù)據(jù)庫的外鍵約束中設(shè)置ON DELETE CASCADE規(guī)則。
2、使用您自己的代碼先刪除阻止父對象被刪除的子對象。
如果無法保證上述至少一個條件成立,則將拋出異常。請參閱本主題的第二個代碼示例。
刪除數(shù)據(jù)庫中某一行的操作如下:
- 1、在數(shù)據(jù)庫中查詢需要刪除的行。
- 2、調(diào)用DeleteOnSubmit方法。
- 3、將刪除操作提交到數(shù)據(jù)庫。
下面的第1個代碼示例向數(shù)據(jù)庫查詢屬于order# 11000的訂單詳細信息,將這些訂單詳細信息標記為刪除,并將這些更改提交給數(shù)據(jù)庫。
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. }
在第二個代碼示例中,目標是刪除一個訂單(#10250)。代碼首先檢查OrderDetails表,以查看要刪除的訂單在那里是否有子訂單。如果訂單有子訂單,則首先將子訂單標記為要刪除,然后將訂單標記為要刪除。DataContext將實際的刪除按正確的順序排列,以便發(fā)送到數(shù)據(jù)庫的刪除命令遵守數(shù)據(jù)庫約束。
//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é)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
C#中Thread(線程)和Task(任務(wù))實例詳解
.NET Framework在System.Threading命名空間中具有與線程相關(guān)的類,線程是一小組可執(zhí)行指令,這篇文章主要給大家介紹了關(guān)于C#中Thread(線程)和Task(任務(wù))的相關(guān)資料,需要的朋友可以參考下2022-03-03C#實現(xiàn)文件讀寫到SQLite數(shù)據(jù)庫
這篇文章主要為大家詳細介紹了使用?C#?將文件讀寫到?SQLite?數(shù)據(jù)庫的幾種方法,文中的示例代碼講解詳細,感興趣的小伙伴可以參考一下2025-01-01