建立實體類
使用LINQ to SQL時,需要首先建立用于映射數據庫對象的模型,也就是實體類。在運行時,LINQ to SQL 根據LINQ表達式或查詢運算符生成SQL語句,發送到數據庫進行操作。數據庫返回后,LINQ to SQL負責將結果轉換成實體類對象。
建立實體類的方法有很多,例如LINQ to SQL設計器,手動編碼建立,使用XML文件映射,使用命令行工具SqlMetal生成等。其中最方便的就是LINQ to SQL設計器。
1.使用LINQ to SQL設計器建立實體類
在一個示例用的Demo控制臺程序中添加一個“基于服務的數據庫”Database1.mdf,建立一張tb_GuestInfo的表。該表的詳細如下:
下面的所有建立方式,都用的這個數據庫。
在項目中添加一個LINQ to SQL類,采用默認的名稱DataClasses1.dbml,如下:
將tb_GuestInfo表拖到界面上,保存。
OK,編寫相關代碼如下,實現增刪改查:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace LINQ_To_SQL自定義數據庫和實體類{ /// <summary> /// 實體類的建立___1.VS建立實體類 /// </summary> class Program { static void Main(string[] args) { // DataClasses1DataContext dc = new DataClasses1DataContext(); //1.查詢 IQueryable<tb_GuestInfo> query = from p in dc.tb_GuestInfo where p.Name != "XXX" select p; foreach (var g in query) { Console.WriteLine("{0} {1} {2} {3}",g.Id,g.Name,g.Age ,g.Tel ); } Console.WriteLine("-----------------"); Console.ReadKey(false); //2.增加一條記錄 tb_GuestInfo gInfo = new tb_GuestInfo() { Id = 9, Name = "M&M", Age = 40, Tel = "135****5555" }; dc.tb_GuestInfo.InsertOnSubmit(gInfo); dc.SubmitChanges(); foreach (var g in query) { Console.WriteLine("{0} {1} {2} {3}",g.Id , g.Name, g.Age, g.Tel); } Console.WriteLine("-----------------"); Console.ReadKey(false); //3.刪除 var query_itemToDelete = from g in dc.tb_GuestInfo where g.Name == "M&M" select g; foreach (var g in query_itemToDelete) { dc.tb_GuestInfo.DeleteOnSubmit(g); } dc.SubmitChanges(); foreach (var g in query) { Console.WriteLine("{0} {1} {2} {3}", g.Id, g.Name, g.Age, g.Tel); } Console.WriteLine("-----------------"); Console.ReadKey(false); //4.修改 var query_itemToUpdate = from g in dc.tb_GuestInfo where g.Name.Contains("DebugLZQ") select g; foreach (var g in query_itemToUpdate) { g.Name = g.Name + "A"; } dc.SubmitChanges(); foreach (var g in query) { Console.WriteLine("{0} {1} {2} {3}", g.Id, g.Name, g.Age, g.Tel); } Console.WriteLine("-----------------"); Console.ReadKey(false); } }}
程序運行結果如下:
2.手動建立實體類
實體類在多數情況下可以通過LINQ to SQL類設計器建立,當然動手建立一個簡單的實體類也不是難事,并且可以更好的學習LINQ to SQL的對象模型。數據庫依然是前面的示例數據庫。
在項目中添加一個類GuestInfoEntity.cs,如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data.Linq.Mapping;namespace DataContexDemo{ /// <summary> /// 手動建立實體類 /// </summary> [Table(Name="tb_GuestInfo")] class GuestInfoEntity { [Column(IsPrimaryKey=true,DbType="Int NOT NULL IDENTITY",IsDbGenerated=true,Name="Id")] public int ID { get; set; } [Column(DbType = "nvarchar(20)", Name = "Name")] public string Name{get;set;} [Column(DbType = "int", Name = "Age")] public int Age { get; set; } [Column(DbType = "nvarchar(20)", Name = "Tel")] public string Tel { get; set; } }}
編寫示例代碼,注意需要引入System.Data.Linq.dll:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data.Linq;//關注namespace DataContexDemo{ class Program { static void Main(string[] args) { //2.手動建立實體類 // //連接字符串 string constring = @"Data Source=./SQLEXPRESS;AttachDbFilename=E:/Visual Studio 2010/LINQ_to_SQL/LINQ_To_SQL自定義數據庫和實體類/Database1.mdf;Integrated Security=True;User Instance=True"; DataContext dc = new DataContext(constring); Table<GuestInfoEntity> tb = dc.GetTable<GuestInfoEntity>(); var query = tb.AsEnumerable(); foreach (var q in query) { Console.WriteLine("{0} {1} {2} {3}",q.ID,q.Name,q.Age,q.Tel ); } Console.ReadKey(); } }}
程序運行如下:
3.使用XML映射文件建立實體類
實體類的映射除了使用內聯Attribute外,還可以建立一個包含映射信息的XML文件,此文件生成System.Data.Linq.Mapping.XmlMappingSource對象,作為DataContext對象構造方法的參數。
這個XML文件只有一個根節點---Database元素,用來映射的數據庫信息。Database元素包含一個或多個Table元素,用于映射數據庫表的信息,Table元素由一個Type元素和多個Column元素(或Association元素)組成。Type元素用來指定實體類,Column元素用來指定列信息,Association元素用來映射數據庫關系。
在項目中添加一個XML文件,采用默認名稱XMLFile1.xml,內容如下:
<?xml version="1.0" encoding="utf-8" ?><Database Name="Database1" xmlns="http://schemas.microsoft.com/linqtosql/mapping/2007"><!--數據庫名稱可隨意;名稱空間一定要加上--> <Table Name="tb_GuestInfo"><!--數據庫中表的名稱--> <Type Name="LINQtoSQL建立實體類_XML.GuestInfoEntity"><!--太BT了,居然要全名;GuestInfoEntity居然不行--> <Column Name="Id" Member="ID" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true"/> <Column Name="Name" Member="Name" DbType="nvarchar(20)" /> <Column Name="Age" Member="Age" DbType="int" /> <Column Name="Tel" Member="Tel" DbType="nvarchar(20)" /> </Type> </Table></Database>
這個XML文件包含類全部的映射信息,下面建立映射的類GuestInfoEntity.cs:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace LINQtoSQL建立實體類_XML{ public class GuestInfoEntity { public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public string Tel { get; set; } }}
編寫示例代碼,同樣需要引入System.Data.Linq.dll:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data.Linq;using System.Data.Linq.Mapping;using System.IO;//namespace LINQtoSQL建立實體類_XML{ class Program { static void Main(string[] args) { string constring = @"Data Source=./SQLEXPRESS;AttachDbFilename=E:/Visual Studio 2010/LINQ_to_SQL/LINQ_To_SQL自定義數據庫和實體類/Database1.mdf;Integrated Security=True;User Instance=True"; XmlMappingSource map = XmlMappingSource.FromXml(File.ReadAllText("XMLFile1.xml")); DataContext dc = new DataContext(constring, map); Table<GuestInfoEntity> tb = dc.GetTable<GuestInfoEntity>(); var query = tb.AsEnumerable(); foreach (var g in query) { Console.WriteLine("{0} {1} {2} {3}",g.ID,g.Name,g.Age,g.Tel ); } Console.ReadKey(); } }}
程序的運行如下:
用于數據庫連接的DataContext對象成員
DataContext類位于System.Data.Linq.dll程序集中的System.Data.Linq名稱空間下。在LINQ to SQL中負責實體對象和數據庫之間的數據交換及其他數據庫操作,還負責把數據庫中的數據映射成實體類的實例。
DataContext是LINQ to SQL操作實體類建立后緊接著需要操作的對象。本文總結其常用函數和屬性的作用及常用用法,實體類是上一節的GuestInfo.cs類,數據庫也采用上一節的數據庫Database1.mdb,下面的示例程序對對象和屬性按其功能進行了必要的分組,代碼中也有詳盡的注釋。代碼如下:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Data.Linq;using System.IO;using System.Data.SqlClient;namespace DataContext對象成員{ /// <summary> /// 用于數據庫連接的DataContext類成員 /// </summary> class Program { static void Main(string[] args) { //連接字符串 string constring = @"Data Source=./SQLEXPRESS;AttachDbFilename=E:/Visual Studio 2010/LINQ_to_SQL/LINQ_To_SQL自定義數據庫和實體類/Database1.mdf;Integrated Security=True;User Instance=True"; //1.構造函數 DataContext dc = new DataContext(constring); //2.GetTable Table<GuestInfoEntity> table = dc.GetTable<GuestInfoEntity>(); var query = table.AsEnumerable(); foreach(var g in query) { Console.WriteLine("{0} {1} {2} {3}",g.ID,g.Name,g.Age,g.Tel ); } Console.WriteLine("-----------------"); Console.ReadKey(); string fileName = @"E:/Visual Studio 2010/LINQ_to_SQL/LINQ_To_SQL自定義數據庫和實體類/Database1.mdf"; //3.DatabaseExists、DeleteDatabase、CreateDatabase if (dc.DatabaseExists()) { Console.WriteLine("數據庫文件已經存在."); dc.DeleteDatabase(); } dc.CreateDatabase(); if (dc.DatabaseExists()) { Console.WriteLine("{0} 數據庫文件創建成功.",Path.GetFileName(fileName )); } Console.WriteLine("-----------------"); Console.ReadKey(); //4_1.ExecuteCommand 作為LINQ補充直接用SQL指令操作數據庫 dc.ExecuteCommand("insert into tb_GuestInfo(Name,Age,Tel) values({0},{1},{2})","DebugLZQ",25,"198****1336"); foreach (var r in dc.GetTable<GuestInfoEntity>()) { Console.WriteLine("{0} {1} {2} {3}",r.ID,r.Name,r.Age,r.Tel ); } Console.WriteLine("-----------------"); Console.ReadKey(); //4_2.ExecuteQuery 作為LINQ補充直接用SQL指令操作數據庫 var rows= dc.ExecuteQuery<GuestInfoEntity>("select * from tb_GuestInfo"); foreach (var r in rows) { Console.WriteLine("{0} {1} {2} {3}", r.ID, r.Name, r.Age, r.Tel); } Console.WriteLine("-----------------"); Console.ReadKey(); //4_3Translate 將DbReader轉換為LINQ對象 string queryString = "select * from tb_GuestInfo"; SqlConnection connection = new SqlConnection(constring); SqlCommand cmd = new SqlCommand(queryString, connection); connection.Open(); var result = dc.Translate<GuestInfoEntity>(cmd.ExecuteReader());//ADO.NET轉換LINQ foreach (var r in result) { Console.WriteLine("{0} {1} {2} {3}", r.ID, r.Name, r.Age, r.Tel); } connection.Close(); Console.WriteLine("-----------------"); Console.ReadKey(); //5.SubmitChanges 應用修改 var firstrow = (from p in dc.GetTable<GuestInfoEntity>() select p).First(); firstrow.Name =firstrow.Name +"A"; dc.SubmitChanges();//應用修改 foreach (var r in dc.GetTable<GuestInfoEntity>() ) { Console.WriteLine("{0} {1} {2} {3}", r.ID, r.Name, r.Age, r.Tel); } Console.WriteLine("-----------------"); Console.ReadKey(); //6.GetChangeSet方法 返回DataContext對象插入、刪除、修改過的對象 ChangeSet cs = dc.GetChangeSet(); foreach (var r in cs.Updates ) { GuestInfoEntity t = r as GuestInfoEntity; Console.WriteLine("{0} {1} {2} {3}", t.ID,t.Name,t.Age,t.Tel ); } Console.WriteLine("-----------------"); Console.ReadKey(); //7.Refresh刷新實體對象 var row1=(from g in dc.GetTable<GuestInfoEntity>() select g).First(); row1.Age = row1.Age + 5; dc.SubmitChanges(); dc.Refresh(RefreshMode.OverwriteCurrentValues, row1);// foreach (var r in dc.GetTable<GuestInfoEntity>()) { Console.WriteLine("{0} {1} {2} {3}", r.ID, r.Name, r.Age, r.Tel); } Console.WriteLine("7-----------------"); Console.ReadKey(); //ChangeConflicts屬性 返回DataContext操作數據庫時產生的并發沖突合集 //Transaction屬性 設置或返回DataContext跟其他ADO.NET程序共享的事物對象 //ObjectTrackingEnabled屬性 開啟或關閉DataContext實體對象的狀態跟蹤 //8.Log屬性 返回DataContext產生的SQL命令 dc.Log = Console.Out;//控制臺輸出DataContext產生的SQL語句 foreach (var r in dc.GetTable<GuestInfoEntity>()) { Console.WriteLine("{0} {1} {2} {3}", r.ID, r.Name, r.Age, r.Tel); } Console.WriteLine("-----------------"); Console.ReadKey(); } }}
程序中的注釋很詳細,不再贅述。
程序的運行結果如下:
操作單一表格的Table<TEntity>類
前面介紹了DataContext類,它可以用來映射和連接數據庫,執行SQL命令,跟蹤實體對象的狀態。
下面介紹Table<TEntity>表示表格記錄,它是一個泛型集合類,它的元素就是表格實體對象。它提供一組方法,對元素進行添加刪除操作,并可以通過DataContext將這些操作保存到數據庫。
表還是前面的那張表,在項目中添加了一個LINQ to SQL類。重點是InsertOnSubmit、DeleteOnSubmit等方法。
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace LINQ_to_SQL_Table{ /// <summary> /// 操作單一表格的Table<TEntity>類 /// </summary> class Program { static void Main(string[] args) { //1.a.Attach附加實體 DataClasses1DataContext dc1 = new DataClasses1DataContext(); tb_GuestInfo guset = new tb_GuestInfo() { Id=1, Name = "DebugLZQ", Age = 35, Tel = "138****8888" }; dc1.tb_GuestInfo.Attach(guset);//這樣的Attach僅僅附加實體,數據庫沒有更新 dc1.SubmitChanges(); //顯示附加成功 foreach (var g in dc1.tb_GuestInfo) { Console.WriteLine("{0} {1} {2} {3}", g.Id, g.Name, g.Age, g.Tel); } Console.WriteLine("---------"); //顯示數據庫沒有更新 DataClasses1DataContext dc2 = new DataClasses1DataContext(); foreach (var g in dc2.tb_GuestInfo) { Console.WriteLine("{0} {1} {2} {3}", g.Id, g.Name, g.Age, g.Tel); } Console.WriteLine("------------------------"); Console.ReadKey(); //2.InsertOnSubmit dc2.tb_GuestInfo.InsertOnSubmit(guset); dc2.SubmitChanges(); foreach (var g in dc2.tb_GuestInfo) { Console.WriteLine("{0} {1} {2} {3}", g.Id, g.Name, g.Age, g.Tel); } Console.WriteLine("------------------------"); Console.ReadKey(); //2b.InsertAllOnSubmit 插入集合 List<tb_GuestInfo> lst = new List<tb_GuestInfo>() { new tb_GuestInfo(){ Name="AA", Age=25,Tel="133****3333"}, new tb_GuestInfo(){ Name="BB", Age=25,Tel="135****5555"} }; dc2.tb_GuestInfo.InsertAllOnSubmit(lst); dc2.SubmitChanges(); foreach (var g in dc2.tb_GuestInfo) { Console.WriteLine("{0} {1} {2} {3}", g.Id, g.Name, g.Age, g.Tel); } Console.WriteLine("------------------------"); Console.ReadKey(); // //3.DeleteOnSubmit tb_GuestInfo entity = (from g in dc2.tb_GuestInfo where g.Name == "AA" select g).Single(); dc2.tb_GuestInfo.DeleteOnSubmit(entity);// dc2.SubmitChanges(); foreach (var g in dc2.tb_GuestInfo) { Console.WriteLine("{0} {1} {2} {3}", g.Id, g.Name, g.Age, g.Tel); } Console.WriteLine("------------------------"); Console.ReadKey(); //3b.DeleteAllOnSubmit IEnumerable<tb_GuestInfo> entitys = from g in dc2.tb_GuestInfo where g.Name == "AA" || g.Name == "BB" select g; dc2.tb_GuestInfo.DeleteAllOnSubmit(entitys); dc2.SubmitChanges(); foreach (var g in dc2.tb_GuestInfo) { Console.WriteLine("{0} {1} {2} {3}", g.Id, g.Name, g.Age, g.Tel); } Console.WriteLine("------------------------"); Console.ReadKey(); } }}
程序運行結果如下:
新聞熱點
疑難解答