色尼玛亚洲综合影院,亚洲3atv精品一区二区三区,麻豆freexxxx性91精品,欧美在线91

一步一步學(xué)Linq to sql(八):繼承與關(guān)系

系列文章導(dǎo)航:

一步一步學(xué)Linq to sql(一):預(yù)備知識(shí)

一步一步學(xué)Linq to sql(二):DataContext與實(shí)體

一步一步學(xué)Linq to sql(三):增刪改

一步一步學(xué)Linq to sql(四):查詢句法

一步一步學(xué)Linq to sql(五):存儲(chǔ)過(guò)程

一步一步學(xué)Linq to sql(六):探究特性

一步一步學(xué)Linq to sql(七):并發(fā)與事務(wù)

一步一步學(xué)Linq to sql(八):繼承與關(guān)系

一步一步學(xué)Linq to sql(九):其它補(bǔ)充

一步一步學(xué)Linq to sql(十):分層構(gòu)架的例子


論壇表結(jié)構(gòu)

       為了演示繼承與關(guān)系,我們創(chuàng)建一個(gè)論壇數(shù)據(jù)庫(kù),在數(shù)據(jù)庫(kù)中創(chuàng)建三個(gè)表:

1、  論壇版塊分類表 dbo.Categories

字段名

字段類型

可空

備注

CategoryID

int

not null

identity/主鍵

CategoryName

varchar(50)

not null

 

2、  論壇版塊表 dbo.Boards

字段名

字段類型

可空

備注

BoardID

int

not null

identity/主鍵

BoardName

varchar(50)

not null

 

BoardCategory

int

not null

對(duì)應(yīng)論壇版塊分類表的CategoryID

3、  論壇主題表 dbo.Topics

字段名

字段類型

可空

備注

TopicID

int

not null

identity/主鍵

TopicTitle

varchar(50)

not null

 

TopicContent

varchar(max)

not null

 

ParentTopic

int

null

如果帖子是主題貼這個(gè)字段為null,否則就是所屬主題id

TopicType

tinyint

not null

0 – 主題貼

1 – 回復(fù)帖

 

系列文章導(dǎo)航:

一步一步學(xué)Linq to sql(一):預(yù)備知識(shí)

一步一步學(xué)Linq to sql(二):DataContext與實(shí)體

一步一步學(xué)Linq to sql(三):增刪改

一步一步學(xué)Linq to sql(四):查詢句法

一步一步學(xué)Linq to sql(五):存儲(chǔ)過(guò)程

一步一步學(xué)Linq to sql(六):探究特性

一步一步學(xué)Linq to sql(七):并發(fā)與事務(wù)

一步一步學(xué)Linq to sql(八):繼承與關(guān)系

一步一步學(xué)Linq to sql(九):其它補(bǔ)充

一步一步學(xué)Linq to sql(十):分層構(gòu)架的例子


實(shí)體繼承的定義

       Linq to sql支持實(shí)體的單表繼承,也就是基類和派生類都存儲(chǔ)在一個(gè)表中。對(duì)于論壇來(lái)說(shuō),帖子有兩種,一種是主題貼,一種是回復(fù)帖。那么,我們就先定義帖子基類:

[Table(Name = "Topics")]

public class Topic

{

    [Column(Name = "TopicID", DbType = "int identity", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]

    public int TopicID { get; set; }

 

    [Column(Name = "TopicType", DbType = "tinyint", CanBeNull = false)]

    public int TopicType { get; set; }

 

    [Column(Name = "TopicTitle", DbType = "varchar(50)", CanBeNull = false)]

    public string TopicTitle { get; set; }

 

    [Column(Name = "TopicContent", DbType = "varchar(max)", CanBeNull = false)]

    public string TopicContent { get; set; }

}

       這些實(shí)體的定義大家應(yīng)該很熟悉了。下面,我們?cè)賮?lái)定義兩個(gè)實(shí)體繼承帖子基類,分別是主題貼和回復(fù)貼:

public class NewTopic : Topic

{

    public NewTopic()

    {

        base.TopicType = 0;

    }

}

 

public class Reply : Topic

{

    public Reply()

    {

        base.TopicType = 1;

    }

 

    [Column(Name = "ParentTopic", DbType = "int", CanBeNull = false)]

    public int ParentTopic { get; set; }

}

       對(duì)于主題貼,在數(shù)據(jù)庫(kù)中的TopicType就保存為0,而對(duì)于回復(fù)貼就保存為1。回復(fù)貼還有一個(gè)相關(guān)字段就是回復(fù)所屬主題貼的TopicID。那么,我們?cè)趺锤嬷?/span>Linq to sqlTopicType0的時(shí)候識(shí)別為NewTopic,而1則識(shí)別為Reply那?只需稍微修改一下前面的Topic實(shí)體定義:

[Table(Name = "Topics")]

[InheritanceMapping(Code = 0, Type = typeof(NewTopic), IsDefault = true)]

[InheritanceMapping(Code = 1, Type = typeof(Reply))]

public class Topic

{

    [Column(Name = "TopicID", DbType = "int identity", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]

    public int TopicID { get; set; }

 

    [Column(Name = "TopicType", DbType = "tinyint", CanBeNull = false, IsDiscriminator = true)]

    public int TopicType { get; set; }

 

    [Column(Name = "TopicTitle", DbType = "varchar(50)", CanBeNull = false)]

    public string TopicTitle { get; set; }

 

    [Column(Name = "TopicContent", DbType = "varchar(max)", CanBeNull = false)]

    public string TopicContent { get; set; }

}

       為類加了InheritanceMapping特性定義,0的時(shí)候類型就是NewTopic1的時(shí)候就是Reply。并且為TopicType字段上的特性中加了IsDiscriminator = true,告知Linq to sql這個(gè)字段就是用于分類的字段。

系列文章導(dǎo)航:

一步一步學(xué)Linq to sql(一):預(yù)備知識(shí)

一步一步學(xué)Linq to sql(二):DataContext與實(shí)體

一步一步學(xué)Linq to sql(三):增刪改

一步一步學(xué)Linq to sql(四):查詢句法

一步一步學(xué)Linq to sql(五):存儲(chǔ)過(guò)程

一步一步學(xué)Linq to sql(六):探究特性

一步一步學(xué)Linq to sql(七):并發(fā)與事務(wù)

一步一步學(xué)Linq to sql(八):繼承與關(guān)系

一步一步學(xué)Linq to sql(九):其它補(bǔ)充

一步一步學(xué)Linq to sql(十):分層構(gòu)架的例子


實(shí)體繼承的使用

       定義好繼承的實(shí)體之后,我們就可以使用了。先是自定義一個(gè)DataContext吧:

public partial class BBSContext : DataContext

{

    public Table<BoardCategory> BoardCategories;

    public Table<Board> Boards;

    public Table<Topic> Topics;

    public BBSContext(string connection) : base(connection) { }

}

       然后,我們來(lái)測(cè)試一下Linq to sql是否能根據(jù)TopicType識(shí)別派生類:

        BBSContext ctx = new BBSContext("server=xxx;database=BBS;uid=xxx;pwd=xxx");

        var query = from t in ctx.Topics select t;

        foreach (Topic topic in query)

        {

            if (topic is NewTopic)

            {

                NewTopic newtopic = topic as NewTopic;

                Response.Write("標(biāo)題:" + newtopic.TopicTitle + " 類型:" + newtopic.TopicType + "<br/>");

            }

            else if (topic is Reply)

            {

                Reply reply = topic as Reply;

                Response.Write("標(biāo)題:" + reply.TopicTitle + " 類型:" + reply.TopicType + " 隸屬主題:" + reply.ParentTopic + "<br/>");

            }

        }

       然后我們往Topics表中加一些數(shù)據(jù),如下圖:

       啟動(dòng)程序得到如下測(cè)試結(jié)果:


       當(dāng)然,你也可以在查詢句法中直接查詢派生實(shí)體:

       newtopicreplies是兩個(gè)GridView控件,執(zhí)行效果如下圖:


       再來(lái)看看如何進(jìn)行增刪操作:

        NewTopic nt = new NewTopic() { TopicTitle = "還是新主題", TopicContent = "還是新主題" };

        Reply rpl = new Reply() { TopicTitle = "還是新回復(fù)", TopicContent = "還是新回復(fù)", ParentTopic = 4 };

        ctx.Topics.Add(nt);

        ctx.Topics.Add(rpl);

        ctx.SubmitChanges();

        rpl = ctx.Topics.OfType<Reply>().Single(reply => reply.TopicID == 8);

        ctx.Topics.Remove(rpl);

        ctx.SubmitChanges();

 

系列文章導(dǎo)航:

一步一步學(xué)Linq to sql(一):預(yù)備知識(shí)

一步一步學(xué)Linq to sql(二):DataContext與實(shí)體

一步一步學(xué)Linq to sql(三):增刪改

一步一步學(xué)Linq to sql(四):查詢句法

一步一步學(xué)Linq to sql(五):存儲(chǔ)過(guò)程

一步一步學(xué)Linq to sql(六):探究特性

一步一步學(xué)Linq to sql(七):并發(fā)與事務(wù)

一步一步學(xué)Linq to sql(八):繼承與關(guān)系

一步一步學(xué)Linq to sql(九):其它補(bǔ)充

一步一步學(xué)Linq to sql(十):分層構(gòu)架的例子


實(shí)體關(guān)系的定義

       比如我們的論壇分類表和論壇版塊表之間就有關(guān)系,這種關(guān)系是1對(duì)多的關(guān)系。也就是說(shuō)一個(gè)論壇分類可能有多個(gè)論壇版塊,這是很常見(jiàn)的。定義實(shí)體關(guān)系的優(yōu)勢(shì)在于,我們無(wú)須顯式作連接操作就能處理關(guān)系表的條件。

       首先來(lái)看看分類表的定義:

 

[Table(Name = "Categories")]

public class BoardCategory

{

    [Column(Name = "CategoryID", DbType = "int identity", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]

    public int CategoryID { get; set; }

 

    [Column(Name = "CategoryName", DbType = "varchar(50)", CanBeNull = false)]

    public string CategoryName { get; set; }

 

    private EntitySet<Board> _Boards;

 

    [Association(OtherKey = "BoardCategory", Storage = "_Boards")]

    public EntitySet<Board> Boards

    {

        get { return this._Boards; }

        set { this._Boards.Assign(value); }

    }

 

    public BoardCategory()

    {

        this._Boards = new EntitySet<Board>();

    }

}

       CategoryIDCategoryName的映射沒(méi)有什么不同,只是我們還增加了一個(gè)Boards屬性,它返回的是Board實(shí)體集。通過(guò)特性,我們定義了關(guān)系外鍵為BoardCategoryBoard表的一個(gè)字段)。然后來(lái)看看1對(duì)多,多端版塊表的實(shí)體:

 

[Table(Name = "Boards")]

public class Board

{

    [Column(Name = "BoardID", DbType = "int identity", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false)]

    public int BoardID { get; set; }

 

    [Column(Name = "BoardName", DbType = "varchar(50)", CanBeNull = false)]

    public string BoardName { get; set; }

 

    [Column(Name = "BoardCategory", DbType = "int", CanBeNull = false)]

    public int BoardCategory { get; set; }

 

    private EntityRef<BoardCategory> _Category;

 

    [Association(ThisKey = "BoardCategory", Storage = "_Category")]

    public BoardCategory Category

    {

        get { return this._Category.Entity; }

        set

        {

            this._Category.Entity = value;

            value.Boards.Add(this);

        }

}

}

       在這里我們需要關(guān)聯(lián)分類,設(shè)置了Category屬性使用BoardCategory字段和分類表關(guān)聯(lián)。 


系列文章導(dǎo)航:

一步一步學(xué)Linq to sql(一):預(yù)備知識(shí)

一步一步學(xué)Linq to sql(二):DataContext與實(shí)體

一步一步學(xué)Linq to sql(三):增刪改

一步一步學(xué)Linq to sql(四):查詢句法

一步一步學(xué)Linq to sql(五):存儲(chǔ)過(guò)程

一步一步學(xué)Linq to sql(六):探究特性

一步一步學(xué)Linq to sql(七):并發(fā)與事務(wù)

一步一步學(xué)Linq to sql(八):繼承與關(guān)系

一步一步學(xué)Linq to sql(九):其它補(bǔ)充

一步一步學(xué)Linq to sql(十):分層構(gòu)架的例子


實(shí)體關(guān)系的使用

    好了,現(xiàn)在我們就可以在查詢句法中直接關(guān)聯(lián)表了(數(shù)據(jù)庫(kù)中不一定要設(shè)置表的外鍵關(guān)系):

        Response.Write("-------------查詢分類為1的版塊-------------<br/>");

        var query1 = from b in ctx.Boards where b.Category.CategoryID == 1 select b;

        foreach (Board b in query1)

            Response.Write(b.BoardID + " " + b.BoardName + "<br/>");

        Response.Write("-------------查詢版塊大于2個(gè)的分類-------------<br/>");

        var query2 = from c in ctx.BoardCategories where c.Boards.Count > 2 select c;

        foreach (BoardCategory c in query2)

            Response.Write(c.CategoryID + " " + c.CategoryName + " " + c.Boards.Count + "<br/>");

       在數(shù)據(jù)庫(kù)中加一些測(cè)試數(shù)據(jù),如下圖:

 

       運(yùn)行程序后得到下圖的結(jié)果:

 

       我想定義實(shí)體關(guān)系的方便我不需要再用語(yǔ)言形容了吧。執(zhí)行上述的程序會(huì)導(dǎo)致下面SQL的執(zhí)行:

SELECT [t0].[BoardID], [t0].[BoardName], [t0].[BoardCategory]

FROM [Boards] AS [t0]

INNER JOIN [Categories] AS [t1] ON [t1].[CategoryID] = [t0].[BoardCategory]

WHERE [t1].[CategoryID] = @p0

-- @p0: Input Int32 (Size = 0; Prec = 0; Scale = 0) [1]

 

SELECT [t0].[CategoryID], [t0].[CategoryName]

FROM [Categories] AS [t0]

WHERE ((

    SELECT COUNT(*)

    FROM [Boards] AS [t1]

    WHERE [t1].[BoardCategory] = [t0].[CategoryID]

    )) > @p0

-- @p0: Input Int32 (Size = 0; Prec = 0; Scale = 0) [2]

 

SELECT [t0].[BoardID], [t0].[BoardName], [t0].[BoardCategory]

FROM [Boards] AS [t0]

WHERE [t0].[BoardCategory] = @p0

-- @p0: Input Int32 (Size = 0; Prec = 0; Scale = 0) [1]

        可以看到,第二個(gè)查詢并沒(méi)有做外連接,還記得DataLoadOptions嗎?我們可以要求Linq to sql在讀取版塊分類信息的時(shí)候也把版塊信息一起加載:

DataLoadOptions options = new DataLoadOptions();

        options.LoadWith<BoardCategory>(c => c.Boards);

        ctx.LoadOptions = options;

        Response.Write("-------------查詢版塊大于2個(gè)的分類-------------<br/>");

        var query2 = from c in ctx.BoardCategories where c.Boards.Count > 2 select c;

        foreach (BoardCategory c in query2)

            Response.Write(c.CategoryID + " " + c.CategoryName + " " + c.Boards.Count + "<br/>");

查詢經(jīng)過(guò)改造后會(huì)得到下面的SQL

SELECT [t0].[CategoryID], [t0].[CategoryName], [t1].[BoardID], [t1].[BoardName], [t1].[BoardCategory], (

    SELECT COUNT(*)

    FROM [Boards] AS [t3]

    WHERE [t3].[BoardCategory] = [t0].[CategoryID]

    ) AS [count]

FROM [Categories] AS [t0]

LEFT OUTER JOIN [Boards] AS [t1] ON [t1].[BoardCategory] = [t0].[CategoryID]

WHERE ((

    SELECT COUNT(*)

    FROM [Boards] AS [t2]

    WHERE [t2].[BoardCategory] = [t0].[CategoryID]

    )) > @p0

ORDER BY [t0].[CategoryID], [t1].[BoardID]

-- @p0: Input Int32 (Size = 0; Prec = 0; Scale = 0) [2]

         在添加分類的時(shí)候,如果這個(gè)分類下還有新的版塊,那么提交新增分類的時(shí)候版塊也會(huì)新增:

        BoardCategory dbcat = new BoardCategory() { CategoryName = "Database" };

        Board oracle = new Board() { BoardName = "Oracle", Category = dbcat};

        ctx.BoardCategories.Add(dbcat);

        ctx.SubmitChanges();

       上述代碼導(dǎo)致下面的SQL被執(zhí)行:

INSERT INTO [Categories]([CategoryName]) VALUES (@p0)

 

SELECT [t0].[CategoryID]

FROM [Categories] AS [t0]

WHERE [t0].[CategoryID] = (SCOPE_IDENTITY())

 

-- @p0: Input AnsiString (Size = 8; Prec = 0; Scale = 0) [Database]

 

INSERT INTO [Boards]([BoardName], [BoardCategory]) VALUES (@p0, @p1)

 

SELECT [t0].[BoardID]

FROM [Boards] AS [t0]

WHERE [t0].[BoardID] = (SCOPE_IDENTITY())

 

-- @p0: Input AnsiString (Size = 6; Prec = 0; Scale = 0) [Oracle]

-- @p1: Input Int32 (Size = 0; Prec = 0; Scale = 0) [23]

    今天就講到這里。大家可以自己嘗試為帖子表也定義實(shí)體的關(guān)系,因?yàn)椋遣皇强梢灾苯油ㄟ^(guò)帖子獲取帖子下的回復(fù),或者直接通過(guò)回復(fù)得到所屬帖子那?

it知識(shí)庫(kù)一步一步學(xué)Linq to sql(八):繼承與關(guān)系,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 三穗县| 城固县| 庆云县| 华容县| 浦城县| 乐都县| 桦南县| 上思县| 肇州县| 垦利县| 五华县| 宜州市| 治多县| 江川县| 曲水县| 泸州市| 德庆县| 东乡县| 新余市| 万源市| 郎溪县| 拜城县| 石河子市| 宜君县| 恩施市| 嘉兴市| 敦煌市| 修武县| 太仆寺旗| 顺昌县| 贵南县| 灌南县| 安达市| 日喀则市| 政和县| 嵩明县| 兰西县| 山东省| 旌德县| 安吉县| 陵川县|