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ù)在重復的調(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ù)膶傩灾?。之后將新的Order對象添加到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ù),還有更多復雜的操作,后續(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-03
C#實現(xiàn)文件讀寫到SQLite數(shù)據(jù)庫
這篇文章主要為大家詳細介紹了使用?C#?將文件讀寫到?SQLite?數(shù)據(jù)庫的幾種方法,文中的示例代碼講解詳細,感興趣的小伙伴可以參考一下2025-01-01

