讲讲Linq to SQL映射(基础篇)
??????? 這篇主要講Linq to? SQL基于屬性的映射。即映射數(shù)據(jù)庫(kù),映射表,映射列,映射關(guān)系,映射存儲(chǔ)過程,
映射函數(shù)。然而創(chuàng)建這種映射有三種方法,他們分別是ORD工具,SQLMetal命令行工具,以及編寫手工代碼
創(chuàng)建。
??????? 咱們首先了解下手工創(chuàng)建屬性映射的方法,這樣你就能看懂基于工具產(chǎn)生的代碼了。他們的區(qū)別也就是
使用工具效率會(huì)更高些,但前提需要先設(shè)計(jì)好數(shù)據(jù)庫(kù),這樣就可以直接通過數(shù)據(jù)庫(kù)的結(jié)構(gòu)輸出你的實(shí)體類。
1、映射數(shù)據(jù)庫(kù)
映射數(shù)據(jù)庫(kù)主要通過Database屬性來指定,引用命名空間System.Data.Linq.Mapping;
具體看如下代碼:
//這里在連接的時(shí)候 如果MyDatabase不指定Database屬性,生成的數(shù)據(jù)庫(kù)名為MyDbContext類名//如果指定,則為Database屬性里的名稱,在這里生成的數(shù)據(jù)庫(kù)名為IThinks[Database(Name = "IThinks")]public class MyDbContext : DataContext{//必須構(gòu)建此表,不然創(chuàng)建數(shù)據(jù)庫(kù)時(shí)會(huì)提示沒有表,無法創(chuàng)建。public Table<LoginUser> LoginUsers;public Table<UserBaseInfo> UserBaseInfos;public Table<Aritcal> Articals;public MyDbContext(string connection) : base(connection){}}然后再創(chuàng)建數(shù)據(jù)庫(kù)連接的時(shí)候,就可以這樣寫,如果database 不設(shè)置的話,默認(rèn)的數(shù)據(jù)庫(kù)名就會(huì)為MyDbContext 類名:
MyDbContext db = new MyDbContext("Data Source=localhost;Integrated Security=true;");這樣的話,輸出的連接sql語句為:
2、映射表
映射表使用的attribute屬性為Table
//Table:映射數(shù)據(jù)庫(kù)中對(duì)應(yīng)表或視圖名,NAME指定數(shù)據(jù)庫(kù)表名,若無此表,創(chuàng)建數(shù)據(jù)庫(kù)時(shí),會(huì)自動(dòng)創(chuàng)建 [Table(Name="UserBaseInfo")]public class UserBaseInfo3、映射列
映射列使用的attribute屬性為Column,參數(shù)設(shè)置比較多,具體看如下代碼:
//Column:映射數(shù)據(jù)庫(kù)表中字段 其特性為://Name:數(shù)據(jù)庫(kù)中列的名稱//DbType:數(shù)據(jù)庫(kù)列的數(shù)據(jù)庫(kù)類型//Storage:獲取或設(shè)置私有存儲(chǔ)字段以保存列值//IsPrimaryKey:指示所關(guān)聯(lián)的列是否是相應(yīng)表的主鍵 默認(rèn)false//CanBeNull:指示所關(guān)聯(lián)的列能否包含空值 //CanBeNull不能亂用,如果某列CanBeNull設(shè)置為true,但從數(shù)據(jù)庫(kù)中查出來的值為null的話, //這一列在update的時(shí)候會(huì)提示找不到此行或行已更改,因?yàn)槠洳樵兊恼Z句為where 0 = 1 所以找不到 //可以查看:http://stackoverflow.com/questions/2275442/linq-update-query-generates-where-0-1//如果你非要設(shè)置canbenull=true,可以通過繼續(xù)設(shè)置其updatecheck為never或whenchanged來規(guī)避where 0=1這個(gè)問題。//AutoSync:在執(zhí)行insert或者update操作之后獲取列值,默認(rèn)為never;//UpdateCheck:即設(shè)置是否檢查沖突,默認(rèn)是Always//IsDbGenerated=true 是否數(shù)據(jù)庫(kù)自動(dòng)生成值,如果設(shè)置為true的話,那么在實(shí)例化實(shí)體給此列賦值將會(huì)無效,在執(zhí)行插入時(shí),會(huì)傳值為null進(jìn)入 //如果這時(shí)候數(shù)據(jù)庫(kù)未給予默認(rèn)值或值自增設(shè)置,則會(huì)報(bào)此字段為空的錯(cuò)誤,雖然你在實(shí)例化時(shí)已經(jīng)賦值。 [Column(DbType = "int", IsPrimaryKey = true, IsDbGenerated = true)]public int UserID { get; set; }[Column(DbType = "nvarchar(50) not null", CanBeNull = false, UpdateCheck = UpdateCheck.WhenChanged)]public string UserName { get; set; }[Column(DbType = "nvarchar(50)", CanBeNull = false, UpdateCheck = UpdateCheck.Never)]public string UserNickName { get; set; }4、映射關(guān)系
這里的關(guān)系是指的數(shù)據(jù)庫(kù)中一對(duì)多和一對(duì)一。主鍵基表和外鍵基表的設(shè)置也能通過實(shí)體字段的Association屬性(IsForeignKey=true)來進(jìn)行關(guān)聯(lián),從而在創(chuàng)建數(shù)據(jù)庫(kù)時(shí),自動(dòng)創(chuàng)建表之間的關(guān)系。
但要結(jié)合EntityRef<T>或 EntitySet<T> 來定義并表示一個(gè)關(guān)系
EntityRef代表一對(duì)多關(guān)系中的單一實(shí)例方,EntitySet主要代表一對(duì)多和一對(duì)一關(guān)系中的集合方,下面分別用代碼介紹
以用戶基本信息表 UserBaseInfo和用戶文章表Aritcal來作為介紹,他們是一對(duì)多的關(guān)系
1)EntityRef+Association的使用
因?yàn)镋ntityRef代表的是1:M關(guān)系中的1,所以它應(yīng)該為Aritcal實(shí)體的成員,泛型對(duì)象為UserBaseInfo
這里UserBaseInfo的實(shí)體和Artical實(shí)體分別為:
//Table:映射數(shù)據(jù)庫(kù)中對(duì)應(yīng)表或視圖名,若無此表,會(huì)自動(dòng)創(chuàng)建 [Table(Name = "UserBaseInfo")]public class UserBaseInfo{ [Column(DbType = "int", IsPrimaryKey = true, IsDbGenerated = true)]public int UserID { get; set; }[Column(DbType = "nvarchar(50) not null", CanBeNull = false, UpdateCheck = UpdateCheck.WhenChanged)]public string UserName { get; set; } private EntitySet<Aritcal> _Artiacle;[Association(ThisKey = "UserID", OtherKey = "UserID")]public EntitySet<Aritcal> Articals{get { return _Artiacle; }set { _Artiacle.Assign(value); }}} [Table(Name = "Artical")]public class Aritcal{[Description("文章ID"), Column(IsPrimaryKey = true, CanBeNull = false, DbType = "int not null")]public int ArticalID { get; set; }[Description("用戶ID"), Column(CanBeNull = false, DbType = "int not null")]public int UserID { get; set; }[Description("文章標(biāo)題"), Column(DbType = "nvarchar(100) not null", UpdateCheck = UpdateCheck.Never)]public string ArticalTitle { get; set; }[Description("文章分類"), Column(DbType = "int not null", UpdateCheck = UpdateCheck.Never)]public int CategoryID { get; set; }[Description("模塊分類"), Column(DbType = "int", UpdateCheck = UpdateCheck.Never)]public int ModuleID { get; set; }[Description("文章內(nèi)容"), Column(DbType = "ntext not null", UpdateCheck = UpdateCheck.Never)]public string Content { get; set; } private EntityRef<UserBaseInfo> _UserBaseInfo;//Name:外鍵名//ThisKey:外鍵表的外鍵列 可以不為主鍵 除非1:1關(guān)系中//OtherKey:主鍵表的主鍵列 必須是主鍵//IsForeignKey:是否外鍵//Storage:用來存儲(chǔ)的變量[Association(Name = "FK_Aritcal_UserBaseInfo_UserID", ThisKey = "UserID", OtherKey = "UserID", IsForeignKey = true, Storage = "_UserBaseInfo")]public UserBaseInfo UserBaseInfo{get { return _UserBaseInfo.Entity; }set { _UserBaseInfo.Entity = value; }}}這樣Artical自動(dòng)創(chuàng)建外鍵,生成的表結(jié)構(gòu)關(guān)系為
2)下面在講下EntitySet<T> 和Association
在UserBaseInfo表中創(chuàng)建下面成員,這樣做的好處是,進(jìn)行數(shù)據(jù)庫(kù)關(guān)聯(lián)查詢時(shí)便能查詢出數(shù)據(jù)
private EntitySet<Aritcal> _Artiacle;[Association(ThisKey = "UserID", OtherKey = "UserID")]public EntitySet<Aritcal> Articals{get { return _Artiacle; }set { _Artiacle.Assign(value); }} 見查詢代碼: 查詢用戶信息表中用戶ID為1的用戶信息,通過調(diào)用Articals成員,自動(dòng)關(guān)聯(lián)查詢出用戶id為1的文章列表 UserBaseInfo userbase = db.GetTable<UserBaseInfo>().Where(a => a.UserID == 1).FirstOrDefault();foreach (Aritcal artical in userbase.Articals.ToList()){Console.WriteLine(string.Format("userid:{0} aritical userid:{1} articalid:{2} ispublist{3}",userbase.UserID, artical.UserID, artical.ArticalID, artical.IsPublish));}查詢結(jié)果如下:
5、映射存儲(chǔ)過程
通過調(diào)用Function屬性實(shí)現(xiàn)調(diào)用存儲(chǔ)過程,只有一個(gè)Name特性,來指定存儲(chǔ)過程的名稱
如下面的實(shí)例通過用戶名ID,獲取用戶的密碼:
首先創(chuàng)建存儲(chǔ)過程
create procedure [dbo].[GetPassword] (@userid int , @password nvarchar(30) output ) as begin select @password = c.Password from LoginUser c where c.UserID=@userid end /// <summary>/// 獲取用戶密碼/// </summary>/// <param name="userid">用戶名ID</param>/// <param name="password">用來返回獲取到的密碼</param>/// <returns></returns>[Function(Name = "GetPassword")]public int GetPassword([Parameter(DbType = "int")] int userid, [Parameter(DbType = "nvarchar(30)")] out string password){password = "";IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)MethodInfo.GetCurrentMethod()), userid, password);password = (string)result.GetParameterValue(1); //返回需要的密碼數(shù)據(jù) 必須用out 或者ref引用,不然得到空值return (int)result.ReturnValue; //這里返回0 表示執(zhí)行成功}調(diào)用代碼如下:
string str;db.GetPassword(userbase.UserID, out str);Console.WriteLine("pwd:"+str);調(diào)用結(jié)果如下:
6、映射函數(shù)
用戶自定義函數(shù)(UDF)在linq to sql中用到的屬性是一樣的,不過函數(shù)和存儲(chǔ)過程的區(qū)別導(dǎo)致了函數(shù)只能返回單個(gè)值,而不能像存儲(chǔ)過程那樣返回多個(gè)參數(shù)
具體實(shí)現(xiàn)看如下代碼
首先在數(shù)據(jù)庫(kù)中定義函數(shù)
--創(chuàng)建通過用戶ID獲取密碼的函數(shù) create function Fun_GetPassword (@userid int ) returns nvarchar(30) as begin declare @password nvarchar(30) select @password = c.Password from LoginUser c where c.UserID=@useridreturn @password end然后在vs中編寫代碼調(diào)用
//調(diào)用函數(shù) 這里要加dbo.,不然你若返回的不是表,則會(huì)提示Fun_GetPassword不是可以識(shí)別的 內(nèi)置函數(shù)名稱。//另外調(diào)用函數(shù),要定義IsComposable特性為true,這樣他才知道是調(diào)用的存儲(chǔ)過程[Function(Name = "dbo.Fun_GetPassword", IsComposable = true)]public string Fun_GetPassword([Parameter(DbType = "int")] int userid){IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)MethodInfo.GetCurrentMethod()), userid);return (string)result.ReturnValue;}//調(diào)用自定義函數(shù) 獲取密碼string mypwd= db.Fun_GetPassword(userbase.UserID);Console.WriteLine("pwd:"+mypwd);調(diào)用結(jié)果如下:
下載源碼
您的支持是我最大的動(dòng)力,喜歡就點(diǎn)推薦吧!!!
轉(zhuǎn)載于:https://www.cnblogs.com/flowwind/p/3307373.html
總結(jié)
以上是生活随笔為你收集整理的讲讲Linq to SQL映射(基础篇)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 闺蜜网名韩文一对133个
- 下一篇: MySQL 常用语法 之 DISTINC