<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問(wèn) http://qaseven.github.io/

    步步學(xué)LINQ to SQL:為實(shí)體類添加關(guān)系

      本文詳細(xì)為你闡述了如何在你的應(yīng)用程序中實(shí)現(xiàn)LINQ to SQL。附件的示例程序包括了這里探討的所有代碼,還提供了一個(gè)簡(jiǎn)單的WPF圖形界面程序來(lái)顯示通過(guò)數(shù)據(jù)綁定返回的結(jié)果集。

      本部分描述如何實(shí)現(xiàn)表間的映射關(guān)系:M:1,1:M和M:M。但是這里不會(huì)討論1:1的映射關(guān)系,你可以在M:1的關(guān)系中發(fā)現(xiàn)這種1:1的映射關(guān)系。因此,從這里開(kāi)始,我們將使用Book作為示例為你一步一步講述這一實(shí)現(xiàn)過(guò)程。

      映射M:1的關(guān)系

      Book 對(duì)象與Category 對(duì)象是多對(duì)一的關(guān)系(M:1),因?yàn)橐槐緯?shū)僅能屬于某一個(gè)類別(并且每個(gè)類別能夠包涵很多本書(shū)):

      在數(shù)據(jù)庫(kù)中,Book.catalog字段作為該表的外鍵,而在Category中作為主鍵。然而,在你的對(duì)象模型中,你很可能想讓book.Catalog表示一個(gè)實(shí)際的Catalog對(duì)象(不僅僅是ID)。此時(shí),你可以通過(guò)創(chuàng)建兩個(gè)私有字段來(lái)實(shí)現(xiàn)這一映射關(guān)系,然后再對(duì)Category對(duì)象暴露一個(gè)公有屬性。

      1、添加一個(gè)私有字段以進(jìn)行其他表的關(guān)聯(lián)

      添加一個(gè)私有字段,將其映射到Book.category數(shù)據(jù)庫(kù)表的外鍵列。

      如果允許該字段為NULL,使用一個(gè)空類型即可實(shí)現(xiàn)(如,采用Int?的方式)。

      我將這個(gè)字段命名為categoryId(為了區(qū)別于我們后面將要?jiǎng)?chuàng)建的公有屬性Category)。這意味著在Column特性上我必須得設(shè)置Name參數(shù),因?yàn)槲业淖侄蚊趾蛿?shù)據(jù)庫(kù)表的字段名稱不同:

    [Column( Name="Category")]privateint?categoryId;

      2、添加一個(gè)引用其他表的私有EntityRef類型字段

      添加一個(gè)私有類型的EntityRef字段以實(shí)現(xiàn)對(duì)Category實(shí)例的引用。雖然這會(huì)使得公有屬性Category扮演一個(gè)后臺(tái)字段的角色,但是通過(guò)使用EntityRef類型,仍然能達(dá)到延遲加載的目的(意思是LINQ不會(huì)即時(shí)從數(shù)據(jù)庫(kù)獲取數(shù)據(jù)直到我們真正想要數(shù)據(jù)的時(shí)候)。初始化EntityRef字段實(shí)例,以阻止NullReferenceExceptions發(fā)生。萬(wàn)一在某個(gè)地方你需要使用該對(duì)象的實(shí)例(如,Category)而此時(shí)又沒(méi)有任何實(shí)例(Book)可用。

    privateEntityRef _category=newEntityRef( );

      3、使用[Association]特性添加一個(gè)公有屬性進(jìn)行類的關(guān)聯(lián)

      最后,創(chuàng)建類型為public的Category屬性,該屬性用于接收實(shí)際的Category實(shí)例。 使用下面的參數(shù)為該屬性添加Association特性:

      ● 數(shù)據(jù)庫(kù)兩表之間的是關(guān)系名稱Name(在本例為FK_Books_BookCategories))

      ● IsForeignKey = true標(biāo)記指定該類對(duì)應(yīng)數(shù)據(jù)表的外鍵(在下面的ThisKey參數(shù)中進(jìn)行了指定)。

      ● 使用剛才創(chuàng)建的字段為該特性設(shè)置兩個(gè)參數(shù):

      (1)ThisKey用于指定到其它表的外鍵:categoryId。

      (2)Storage指定EntityRef用于接收其他類的實(shí)例:_category。

      在屬性內(nèi)部,代碼的getter/setter訪問(wèn)器用于使用category的Entity屬性,它包涵實(shí)際的Category實(shí)例:

    [Association( Name = "FK_Books_BookCategories",
    IsForeignKey = true, Storage = "_category", ThisKey = "categoryId" )]
    public Category Category{
    get { return _category.Entity; }
    set { _category.Entity = value; }
    }

      從M:1的關(guān)系上訪問(wèn)數(shù)據(jù)

      現(xiàn)在你可以通過(guò)這種關(guān)系以面向?qū)ο蟮姆绞皆L問(wèn)Category的數(shù)據(jù)。例如,book.Category.Name:

    foreach( var book in bookCatalog.Books ) {
    string categoryName = book.Category.Name;
    }



     在關(guān)聯(lián)表中的M:1關(guān)系

      現(xiàn)在,咱們一起看看如何在M:M關(guān)聯(lián)表中實(shí)現(xiàn)M:1的關(guān)系。當(dāng)我們遇到表之間的關(guān)系為M:M時(shí),正如這里的BookAuthors,當(dāng)然,連接表的關(guān)系仍然是由兩個(gè)M:1關(guān)系構(gòu)成。

      例如,BookAuthor包涵一個(gè)到Book的M:1關(guān)系和一個(gè)到Author的M:1關(guān)系來(lái)構(gòu)成M:M的關(guān)系:

      不幸的是,你仍然需要?jiǎng)?chuàng)建一個(gè)類來(lái)映射這個(gè)關(guān)聯(lián)表。然而,由于外鍵的原因,它僅僅用于映射的關(guān)系,你可以通過(guò)設(shè)置類的訪問(wèn)修飾符為internal來(lái)保持僅對(duì)外提供一個(gè)公共接口。

      1、使用[Table]特性創(chuàng)建一個(gè)內(nèi)部類用于映射需要連接的表

      以BookAuthors類相同的方式創(chuàng)建為其他實(shí)體類,但是不要將其標(biāo)記為public:

    using System.Data.Linq;
    using System.Data.Linq.Mapping;
    namespace LINQDemo
    {
    [Table( Name = "BookAuthors" )]
    class BookAuthor{}
    }

      2、映射兩表之間的M:1關(guān)系,指定它們將其作為主鍵

      為Book和Author創(chuàng)建一個(gè)M:1的關(guān)系并以相同的方式為Book:Catalog創(chuàng)建關(guān)系。注意數(shù)據(jù)庫(kù)中BookAuthors表的關(guān)系以下面的方式命名:

      ● BookAuthor:Authors關(guān)系被命名為 FK_BookAuthors_Authors

      ● BookAuthor:Books 關(guān)系被命名為FK_BookAuthors_Books

      分別在它的兩個(gè)Column特性上為其添加IsPrimaryKey = true的屬性以指示BookAuthors的主鍵由這兩個(gè)值構(gòu)成:

    [Table( Name = "BookAuthors" )]
    class BookAuthor
    {
    [Column( IsPrimaryKey = true, Name = "Author" )] private int authorId;
    private EntityRef _author = new EntityRef( );
    [Association( Name = "FK_BookAuthors_Authors", IsForeignKey = true,
    Storage = "_author", ThisKey = "authorId" )]
    public Author Author {
    get { return _author.Entity; }
    set { _author.Entity = value; }
    }
    Column( IsPrimaryKey = true, Name = "Book" )] private int bookId;
    private EntityRef _book = new EntityRef( );
    [Association( Name = "FK_BookAuthors_Books", IsForeignKey = true,
    Storage = "_book", ThisKey = "bookId" )]
    public Book Book {
    get { return _book.Entity; }
    set { _book.Entity = value; }
    }
    }

      雖然我們已經(jīng)探討了M:1的關(guān)系,但不幸的是,你仍然還不能使用BookAuthor做一些有趣的事,當(dāng)我們?cè)谙旅嬗懻揗:M的關(guān)系時(shí),將繼續(xù)回到表連接的探討話題上來(lái)。但首先,通過(guò)理解如何映射1:M的關(guān)系,我們可以看看Book:Catalog的關(guān)系來(lái)完整理解M:M的關(guān)系。

      映射1:M關(guān)系

      添加一個(gè)1:M的關(guān)系使得你可以獲得一個(gè)屬于Category的所有書(shū)籍列表。

      1、在其它類中映射外鍵

      即使你正在為Category添加關(guān)聯(lián)關(guān)系,它仍然需要知道如何關(guān)聯(lián)到Book本身。因此,你僅需要確保你的Book類已經(jīng)映射到了對(duì)應(yīng)的列,該列應(yīng)該是關(guān)聯(lián)到Category的外鍵。如果你這樣實(shí)現(xiàn),那么你已經(jīng)完成了1:M的關(guān)系,因此這時(shí)你所要做的就是指定字段名:categoryId:

     

    [Table( Name = "Books" )]
    public class Book
    {
    ...
    [Column( Name = "Category" )] private int? categoryId;

     

      2、映射你自己的主鍵

      LINQ會(huì)比較Book的外鍵和Category的外鍵,因此你需要映射Category.Id并標(biāo)識(shí)其作為主鍵([Column (IsPrimaryKey = true)])。再次,如果你繼續(xù)這個(gè)步驟,你已經(jīng)在實(shí)體類中完成了該過(guò)程的創(chuàng)建。因此,所要做的僅僅是為該屬性名Id添加一個(gè)注釋:

     

    [Table (Name="BookCategories")]
    public class Category
    {
    [Column ( IsPrimaryKey = true, IsDbGenerated = true )] public int Id { get; set; }
    ...

     

      3、添加一個(gè)私有的EntitySet類型以實(shí)現(xiàn)對(duì)其他表的引用

      添加一個(gè)私有的EntitySet字段來(lái)接收屬于該Category的書(shū)籍。這將讓我們的公有Books屬性扮演字段的角色。類似地,EntityRef,EntitySet會(huì)引起對(duì)Books的加載延遲直到我們實(shí)際訪問(wèn)它的時(shí)候(因此,當(dāng)我們需要查看一個(gè)類別的時(shí)候,我們不必每次都返回所有書(shū)的列表)。

      初始化EntitySet字段以避免NullReferenceExceptions異常的發(fā)生,比如在你沒(méi)有設(shè)置兩邊關(guān)系的時(shí)候(如一個(gè)類別沒(méi)有書(shū)籍的時(shí)候)

     

    private EntitySet _books = new EntitySet();

     

      4、為相關(guān)聯(lián)的類添加屬性

      最后創(chuàng)建公有Books屬性,它用于接收在對(duì)應(yīng)類別中的書(shū)籍。為該屬性添加一個(gè)Association特性。并設(shè)置數(shù)據(jù)庫(kù)關(guān)系的名稱參數(shù)為Name (FK_Books_BookCategories),以及使用剛才創(chuàng)建這個(gè)字段的特性所需要的三個(gè)參數(shù):

      ● OtherKey指定關(guān)聯(lián)到其他類(Book)的字段,該字段接收所關(guān)聯(lián)的外鍵:categoryId

      ● ThisKey指定你的主鍵(OtherKey所應(yīng)該匹配的字段):Id

      ● Storage指定你的EntitySet類型,該類型用來(lái)存儲(chǔ)相關(guān)聯(lián)的Books集合:_books.

      在屬性內(nèi)部,代碼getter/setter訪問(wèn)修飾符使用了 _books,它包涵一個(gè)實(shí)際Book實(shí)例的ICollection集合:

     

    [Association( Name = "FK_Books_BookCategories",
    Storage = "_books", OtherKey = "categoryId", ThisKey = "Id" )]
    public ICollection Books {
    get { return _books; }
    set { _books.Assign( value ); }
    }

     

      從1:M 關(guān)系上訪問(wèn)數(shù)據(jù)

      現(xiàn)在,你可以通過(guò)使用category.Books屬性訪問(wèn)每個(gè)類別中的Books列表:

     

    foreach( var category in bookCatalog.Categories ){
    foreach( Book book in category.Books ){
    string bookTitle = book.Title;
    }
    }



      映射M:M 關(guān)系

      最后,添加M:M關(guān)系,這可以允許你直接從Book實(shí)例中訪問(wèn)每個(gè)目錄下下的所有作者,以及從Author實(shí)例中直接訪問(wèn)某個(gè)作者寫的所有書(shū)籍。

      通過(guò)創(chuàng)建BookAuthor類,說(shuō)明你已經(jīng)完成了該任務(wù)的大部分工作了。并且,你也在前面部分已經(jīng)了解到當(dāng)你需要?jiǎng)?chuàng)建1:M時(shí)如何實(shí)現(xiàn)這一功能。現(xiàn)在,是該將它們整合起來(lái)的時(shí)候了。再次,我們將使用Book作為示例進(jìn)行闡述。

      1、從類到關(guān)聯(lián)的表上添加一個(gè)1:M的關(guān)系

      Book到BookAuthor 它存在一個(gè)1:M的關(guān)系,每本書(shū)都可以有多個(gè)作者,但是每本書(shū)作者僅僅屬于一本書(shū)。因此,你必須得從先前已有的部分開(kāi)始進(jìn)行如下四個(gè)步驟:

      ● bookId. 在BookAuthor類中映射到Book的外鍵。你已經(jīng)這樣實(shí)現(xiàn)了,會(huì)調(diào)用它的:bookId。

      ● 為Book對(duì)象定義主鍵。你也已經(jīng)這樣實(shí)現(xiàn)了,會(huì)調(diào)用它的:Id。

      ● Add an EntitySet that references the other table: _bookAuthors. 添加一個(gè)引用其他表的EntitySet類型。

      ● 添加一個(gè)BookAuthors屬性(將其設(shè)置為私有的,因?yàn)檫@里僅僅用于幫助獲得作者列表),該屬性添加了Association特性并為其設(shè)置前面部分設(shè)置的三個(gè)參數(shù)值。

      添加Book對(duì)象代碼的第3和第4步如下:

    [Table( Name = "Books" )]
    public class Book
    {
    ...
    private EntitySet _bookAuthors = new EntitySet( );
    [Association( Name = "FK_BookAuthors_Books",
    Storage = "_bookAuthors", OtherKey = "bookId",
    ThisKey = "Id" )]
    private ICollection BookAuthors {
    get { return _bookAuthors; }
    set { _bookAuthors.Assign( value ); }
    }

      雖然你可以在Author中實(shí)現(xiàn)相同的功能(因?yàn)槊總€(gè)作者都可以有多本書(shū)),但是使用authorId取代bookId:

    [Table( Name = "Authors" )]
    public class Author
    {
    ...
    private EntitySet _bookAuthors = new EntitySet( );
    [Association( Name = "FK_BookAuthors_Authors",
    Storage = "_bookAuthors",
    OtherKey = "authorId", ThisKey = "Id" )]
    private ICollection BookAuthors {
    get { return _bookAuthors; }
    set { _bookAuthors.Assign( value ); }
    }

      2、添加一個(gè)公有屬性,通過(guò)1:M的關(guān)系使用LINQ 來(lái)檢索枚舉數(shù)據(jù)。

      最后,通過(guò)創(chuàng)建Authors屬性從該書(shū)實(shí)例的私有書(shū)作者列表中檢索所有作者。例如,如果你有一本LINQ In Action的書(shū),該書(shū)就有三個(gè)作者:Fabrice Marguerie, Steve Eichert, 和Jim Wooley,那么LINQ In Action Book實(shí)例將包涵三個(gè)BookAuthors的列表:


    posted on 2011-11-24 16:43 順其自然EVO 閱讀(292) 評(píng)論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫(kù)

    <2011年11月>
    303112345
    6789101112
    13141516171819
    20212223242526
    27282930123
    45678910

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 日美韩电影免费看| 国产免费内射又粗又爽密桃视频| 日韩版码免费福利视频| 免费在线中文日本| 亚洲一级片在线播放| 亚洲国产精品成人综合色在线婷婷| 亚洲福利视频一区| 亚洲一区二区在线视频| 亚洲精品免费观看| 亚洲美女aⅴ久久久91| 亚洲欧洲高清有无| 亚洲av无码一区二区三区天堂古代 | 国产成+人+综合+亚洲专| 亚洲免费视频观看| 亚洲熟妇无码AV| 亚洲AV日韩AV无码污污网站| WWW亚洲色大成网络.COM | 亚洲视频在线观看免费视频| 亚洲理论片在线观看| 亚洲国产成a人v在线| 亚洲性色精品一区二区在线| 国产精品亚洲二区在线| 久久www免费人成看国产片| 99热在线日韩精品免费| 免费人成在线观看网站品爱网| 2022久久国产精品免费热麻豆| 久久久久久久久免费看无码| 成人a免费α片在线视频网站| 日本一道一区二区免费看 | 国产免费观看青青草原网站| 亚洲第一网站男人都懂| 亚洲精品无码久久久久去q | 久久精品国产亚洲AV麻豆~| 亚洲永久中文字幕在线| 亚洲乱妇老熟女爽到高潮的片| 美女被暴羞羞免费视频| 国产真人无码作爱免费视频 | 久久高潮一级毛片免费| 2020因为爱你带字幕免费观看全集| 毛片a级毛片免费观看免下载| 亚洲А∨精品天堂在线|