講講Linq to SQL映射(基礎篇)


        這篇主要講Linq to  SQL基於屬性的映射。即映射數據庫,映射表,映射列,映射關系,映射存儲過程,

映射函數。然而創建這種映射有三種方法,他們分別是ORD工具,SQLMetal命令行工具,以及編寫手工代碼

創建。

        咱們首先了解下手工創建屬性映射的方法,這樣你就能看懂基於工具產生的代碼了。他們的區別也就是

使用工具效率會更高些,但前提需要先設計好數據庫,這樣就可以直接通過數據庫的結構輸出你的實體類。

1、映射數據庫

映射數據庫主要通過Database屬性來指定,引用命名空間System.Data.Linq.Mapping;

具體看如下代碼:

//這里在連接的時候 如果MyDatabase不指定Database屬性,生成的數據庫名為MyDbContext類名
    //如果指定,則為Database屬性里的名稱,在這里生成的數據庫名為IThinks
    [Database(Name = "IThinks")]
    public class MyDbContext : DataContext
    {
        //必須構建此表,不然創建數據庫時會提示沒有表,無法創建。
        public Table<LoginUser> LoginUsers;
        public Table<UserBaseInfo> UserBaseInfos;
        public Table<Aritcal> Articals;
        public MyDbContext(string connection)  : base(connection)
        {
        }
    }

然后再創建數據庫連接的時候,就可以這樣寫,如果database 不設置的話,默認的數據庫名就會為MyDbContext 類名:

MyDbContext db = new MyDbContext("Data Source=localhost;Integrated Security=true;");

這樣的話,輸出的連接sql語句為:

QQ20130904233637_thumb13

2、映射表

映射表使用的attribute屬性為Table

//Table:映射數據庫中對應表或視圖名,NAME指定數據庫表名,若無此表,創建數據庫時,會自動創建 
    [Table(Name="UserBaseInfo")]
    public class UserBaseInfo

3、映射列

映射列使用的attribute屬性為Column,參數設置比較多,具體看如下代碼:

       //Column:映射數據庫表中字段 其特性為:
       //Name:數據庫中列的名稱
        //DbType:數據庫列的數據庫類型
        //Storage:獲取或設置私有存儲字段以保存列值
        //IsPrimaryKey:指示所關聯的列是否是相應表的主鍵 默認false
       //CanBeNull:指示所關聯的列能否包含空值 
        //CanBeNull不能亂用,如果某列CanBeNull設置為true,但從數據庫中查出來的值為null的話,
          //這一列在update的時候會提示找不到此行或行已更改,因為其查詢的語句為where 0 = 1 所以找不到 //可以查看:http://stackoverflow.com/questions/2275442/linq-update-query-generates-where-0-1
           //如果你非要設置canbenull=true,可以通過繼續設置其updatecheck為never或whenchanged來規避where 0=1這個問題。 //AutoSync:在執行insert或者update操作之后獲取列值,默認為never;
        //UpdateCheck:即設置是否檢查沖突,默認是Always
        //IsDbGenerated=true 是否數據庫自動生成值,如果設置為true的話,那么在實例化實體給此列賦值將會無效,在執行插入時,會傳值為null進入
           //如果這時候數據庫未給予默認值或值自增設置,則會報此字段為空的錯誤,雖然你在實例化時已經賦值。 

        [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、映射關系

這里的關系是指的數據庫中一對多和一對一。主鍵基表和外鍵基表的設置也能通過實體字段的Association屬性(IsForeignKey=true)來進行關聯,從而在創建數據庫時,自動創建表之間的關系。

但要結合EntityRef<T>或 EntitySet<T> 來定義並表示一個關系

EntityRef代表一對多關系中的單一實例方,EntitySet主要代表一對多和一對一關系中的集合方,下面分別用代碼介紹

以用戶基本信息表 UserBaseInfo和用戶文章表Aritcal來作為介紹,他們是一對多的關系

1)EntityRef+Association的使用

因為EntityRef代表的是1:M關系中的1,所以它應該為Aritcal實體的成員,泛型對象為UserBaseInfo

這里UserBaseInfo的實體和Artical實體分別為:

  //Table:映射數據庫中對應表或視圖名,若無此表,會自動創建 
    [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("文章標題"), 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("文章內容"), Column(DbType = "ntext not null", UpdateCheck = UpdateCheck.Never)]
        public string Content { get; set; }
        private EntityRef<UserBaseInfo> _UserBaseInfo;
        //Name:外鍵名
        //ThisKey:外鍵表的外鍵列  可以不為主鍵 除非1:1關系中
        //OtherKey:主鍵表的主鍵列 必須是主鍵
        //IsForeignKey:是否外鍵
        //Storage:用來存儲的變量
        [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自動創建外鍵,生成的表結構關系為

QQ20130905210648_thumb

2)下面在講下EntitySet<T> 和Association

在UserBaseInfo表中創建下面成員,這樣做的好處是,進行數據庫關聯查詢時便能查詢出數據

        private EntitySet<Aritcal> _Artiacle;
        [Association(ThisKey = "UserID", OtherKey = "UserID")]
        public EntitySet<Aritcal> Articals
        {
            get { return _Artiacle; }
            set { _Artiacle.Assign(value); }
        }
見查詢代碼:  查詢用戶信息表中用戶ID為1的用戶信息,通過調用Articals成員,自動關聯查詢出用戶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));
            }

查詢結果如下:

QQ20130905210649_thumb

5、映射存儲過程

通過調用Function屬性實現調用存儲過程,只有一個Name特性,來指定存儲過程的名稱

如下面的實例通過用戶名ID,獲取用戶的密碼:

首先創建存儲過程

create  procedure [dbo].[GetPassword]
(@userid int ,
@password nvarchar(30) output
)
as 
begin
select @password = c.Password from LoginUser c where c.UserID=@userid
end
然后在MyDbContext類中添加如下方法
        /// <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); //返回需要的密碼數據 必須用out 或者ref引用,不然得到空值
            return (int)result.ReturnValue; //這里返回0 表示執行成功
        }

調用代碼如下:

           string  str;
           db.GetPassword(userbase.UserID,  out str);
           Console.WriteLine("pwd:"+str);

調用結果如下:

QQ20130905210650_thumb

6、映射函數

用戶自定義函數(UDF)在linq to sql中用到的屬性是一樣的,不過函數和存儲過程的區別導致了函數只能返回單個值,而不能像存儲過程那樣返回多個參數

具體實現看如下代碼

首先在數據庫中定義函數

--創建通過用戶ID獲取密碼的函數
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=@userid
 return  @password
end

然后在vs中編寫代碼調用

       //調用函數 這里要加dbo.,不然你若返回的不是表,則會提示Fun_GetPassword不是可以識別的 內置函數名稱。
        //另外調用函數,要定義IsComposable特性為true,這樣他才知道是調用的存儲過程
        [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;
        }

            //調用自定義函數 獲取密碼
           string mypwd= db.Fun_GetPassword(userbase.UserID);
           Console.WriteLine("pwd:"+mypwd);

調用結果如下:

QQ20130905210650_thumb3

下載源碼

您的支持是我最大的動力,喜歡就點推薦吧!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM