NBear学习之路1:利用视图创建多表关联的实体
若还不清楚NBear中如何实现ORM,请先阅读Teddy所写的《NBearV3 Step by Step教程——ORM篇》。
通常在一些应用中所使用到的字段不仅仅来左一个数据表,如一个文章列表GirdView中,使用到了Content、User、Category三个表中的项。
关系图如下:
而每个表对应的实体是通过NBear创建的,如果在绑定GirdView时,使用Content[]来做DataSource,再通过强类型来获得Content.User和Content.Category,这样每次都会进行两次查询,如果绑定的列有N条,再绑定一个GirdView的总查询次数将为2N+1。
例如:
而通常我们需要使用多数据表中的数据项时,通常都是使用视图的,而NBear强大的支持从视图生成实体的功能,这样,可以轻而易举地解决这类问题,并且将查询次数减到最少。
1.首先,先建立关联三个表项的视图。结合上面的实体定义的SQL视图脚本如下:
2.使用NBear.Tools.DbToEntityDesign.exe工具从数据库中生成实体定义代码:
3.使用ContentView[]绑定到GirdView即可一次获取所要的结果。
通常在一些应用中所使用到的字段不仅仅来左一个数据表,如一个文章列表GirdView中,使用到了Content、User、Category三个表中的项。
关系图如下:
Content.cs
1 public interface Content : Entity
2 {
3 [PrimaryKey]
4 int ID
5 {
6 get;
7 }
8
9 [ManyToManyQuery(typeof(ContentTag), LazyLoad = true)]
10 Tag[] Tags
11 { get;set; }
12
13 [FkReverseQuery(LazyLoad = false)]
14 Category Category
15 {
16 get;
17 set;
18 }
19
20 DateTime? ModifiedDate
21 {
22 get;
23 set;
24 }
25
26 [FkReverseQuery(LazyLoad = false)]
27 [MappingName("UserID")]
28 User User
29 {
30 get;
31 set;
32 }
33
34 [SqlType("nvarchar(100)")]
35 string Title
36 {
37 get;
38 set;
39 }
40
41 [SqlType("ntext")]
42 string Body
43 {
44 get;
45 set;
46 }
47
48 [SqlType("ntext")]
49 string Summary { get;set;}
50
51 [SqlType("nvarchar(250)")]
52 string Link
53 {
54 get;
55 set;
56 }
57
58 int TopSort
59 {
60 get;
61 set;
62 }
63
64 bool Visible
65 {
66 get;
67 set;
68 }
69
70 int Hits
71 {
72 get;
73 set;
74 }
75
76 [SqlType("nvarchar(50)")]
77 string IP
78 {
79 get;
80 set;
81 }
82
83 bool AllowComment
84 {
85 get;
86 set;
87 }
88
89 int CommentCount
90 {
91 get;
92 set;
93 }
94
95 [FkQuery("Content", OrderBy = "{ID} DESC", Contained = true, LazyLoad = true)]
96 Comment[] Comments
97 {
98 get;
99 set;
100 }
101 }
1 public interface Content : Entity
2 {
3 [PrimaryKey]
4 int ID
5 {
6 get;
7 }
8
9 [ManyToManyQuery(typeof(ContentTag), LazyLoad = true)]
10 Tag[] Tags
11 { get;set; }
12
13 [FkReverseQuery(LazyLoad = false)]
14 Category Category
15 {
16 get;
17 set;
18 }
19
20 DateTime? ModifiedDate
21 {
22 get;
23 set;
24 }
25
26 [FkReverseQuery(LazyLoad = false)]
27 [MappingName("UserID")]
28 User User
29 {
30 get;
31 set;
32 }
33
34 [SqlType("nvarchar(100)")]
35 string Title
36 {
37 get;
38 set;
39 }
40
41 [SqlType("ntext")]
42 string Body
43 {
44 get;
45 set;
46 }
47
48 [SqlType("ntext")]
49 string Summary { get;set;}
50
51 [SqlType("nvarchar(250)")]
52 string Link
53 {
54 get;
55 set;
56 }
57
58 int TopSort
59 {
60 get;
61 set;
62 }
63
64 bool Visible
65 {
66 get;
67 set;
68 }
69
70 int Hits
71 {
72 get;
73 set;
74 }
75
76 [SqlType("nvarchar(50)")]
77 string IP
78 {
79 get;
80 set;
81 }
82
83 bool AllowComment
84 {
85 get;
86 set;
87 }
88
89 int CommentCount
90 {
91 get;
92 set;
93 }
94
95 [FkQuery("Content", OrderBy = "{ID} DESC", Contained = true, LazyLoad = true)]
96 Comment[] Comments
97 {
98 get;
99 set;
100 }
101 }
User.cs
1public interface User : Entity
2 {
3 [PrimaryKey]
4 int ID
5 {
6 get;
7 }
8
9 [SqlType("nvarchar(50)")]
10 string Name
11 {
12 get;
13 set;
14 }
15
16 [SqlType("nvarchar(50)")]
17 string Email
18 {
19 get;
20 set;
21 }
22
23 [FkQuery("UserID", Contained = true, LazyLoad = true)]
24 UserProfile Profile
25 {
26 get;
27 set;
28 }
29
30 [ManyToManyQuery(typeof(UserGroup), OrderBy = "{Name} DESC", LazyLoad = true)]
31 [SerializationIgnore]
32 Group[] Groups
33 {
34 get;
35 set;
36 }
37
38 [ManyToManyQuery(typeof(UserRole), OrderBy = "{Name} DESC", LazyLoad = true)]
39 [SerializationIgnore]
40 Role[] Roles
41 {
42 get;
43 set;
44 }
45
46 [FkQuery("UserID", OrderBy = "{Name} DESC", Contained = true, LazyLoad = true)]
47 [SerializationIgnore]
48 Tag[] Tags
49 {
50 get;
51 set;
52 }
53
54 [FkQuery("User", OrderBy = "{ID} DESC", Contained = true, LazyLoad = true)]
55 [SerializationIgnore]
56 Content[] Contents
57 {
58 get;
59 set;
60 }
61
62 [FkQuery("User", OrderBy = "{ID} DESC", Contained = true, LazyLoad = true)]
63 [SerializationIgnore]
64 Comment[] Comments
65 {
66 get;
67 set;
68 }
69
70 [FkQuery("User", OrderBy = "{Name} DESC", Contained = true, LazyLoad = true)]
71 [SerializationIgnore]
72 Category[] Categories
73 {
74 get;
75 set;
76 }
77
78 UserStatus Status
79 {
80 get;
81 set;
82 }
83
84 [SqlType("nvarchar(50)")]
85 string LogOnName
86 {
87 get;
88 set;
89 }
90
91 [SqlType("nvarchar(50)")]
92 string Password
93 {
94 get;
95 set;
96 }
97
98 [SqlType("nvarchar(100)")]
99 string PassQuestion
100 {
101 get;
102 set;
103 }
104
105 [SqlType("nvarchar(100)")]
106 string PassAnswer
107 {
108 get;
109 set;
110 }
111
112 [FkQuery("UserID", Contained = true, LazyLoad = true)]
113 UserPhone[] Phones
114 {
115 get;
116 set;
117 }
118
119 [SqlType("nvarchar(30)")]
120 string No
121 {
122 get;
123 set;
124 }
125
126 [SqlType("nvarchar(4)")]
127 string Sex
128 {
129 get;
130 set;
131 }
132
133 DateTime? Birthday
134 {
135 get;
136 set;
137 }
138
139 DateTime? CreateDate
140 {
141 get;
142 set;
143 }
144
145 DateTime? LogOnDate
146 {
147 get;
148 set;
149 }
150
151 int LogOnCount
152 {
153 get;
154 set;
155 }
156 }
1public interface User : Entity
2 {
3 [PrimaryKey]
4 int ID
5 {
6 get;
7 }
8
9 [SqlType("nvarchar(50)")]
10 string Name
11 {
12 get;
13 set;
14 }
15
16 [SqlType("nvarchar(50)")]
17 string Email
18 {
19 get;
20 set;
21 }
22
23 [FkQuery("UserID", Contained = true, LazyLoad = true)]
24 UserProfile Profile
25 {
26 get;
27 set;
28 }
29
30 [ManyToManyQuery(typeof(UserGroup), OrderBy = "{Name} DESC", LazyLoad = true)]
31 [SerializationIgnore]
32 Group[] Groups
33 {
34 get;
35 set;
36 }
37
38 [ManyToManyQuery(typeof(UserRole), OrderBy = "{Name} DESC", LazyLoad = true)]
39 [SerializationIgnore]
40 Role[] Roles
41 {
42 get;
43 set;
44 }
45
46 [FkQuery("UserID", OrderBy = "{Name} DESC", Contained = true, LazyLoad = true)]
47 [SerializationIgnore]
48 Tag[] Tags
49 {
50 get;
51 set;
52 }
53
54 [FkQuery("User", OrderBy = "{ID} DESC", Contained = true, LazyLoad = true)]
55 [SerializationIgnore]
56 Content[] Contents
57 {
58 get;
59 set;
60 }
61
62 [FkQuery("User", OrderBy = "{ID} DESC", Contained = true, LazyLoad = true)]
63 [SerializationIgnore]
64 Comment[] Comments
65 {
66 get;
67 set;
68 }
69
70 [FkQuery("User", OrderBy = "{Name} DESC", Contained = true, LazyLoad = true)]
71 [SerializationIgnore]
72 Category[] Categories
73 {
74 get;
75 set;
76 }
77
78 UserStatus Status
79 {
80 get;
81 set;
82 }
83
84 [SqlType("nvarchar(50)")]
85 string LogOnName
86 {
87 get;
88 set;
89 }
90
91 [SqlType("nvarchar(50)")]
92 string Password
93 {
94 get;
95 set;
96 }
97
98 [SqlType("nvarchar(100)")]
99 string PassQuestion
100 {
101 get;
102 set;
103 }
104
105 [SqlType("nvarchar(100)")]
106 string PassAnswer
107 {
108 get;
109 set;
110 }
111
112 [FkQuery("UserID", Contained = true, LazyLoad = true)]
113 UserPhone[] Phones
114 {
115 get;
116 set;
117 }
118
119 [SqlType("nvarchar(30)")]
120 string No
121 {
122 get;
123 set;
124 }
125
126 [SqlType("nvarchar(4)")]
127 string Sex
128 {
129 get;
130 set;
131 }
132
133 DateTime? Birthday
134 {
135 get;
136 set;
137 }
138
139 DateTime? CreateDate
140 {
141 get;
142 set;
143 }
144
145 DateTime? LogOnDate
146 {
147 get;
148 set;
149 }
150
151 int LogOnCount
152 {
153 get;
154 set;
155 }
156 }
Category.cs
1public interface Category : Entity
2 {
3 [PrimaryKey]
4 int ID
5 {
6 get;
7 }
8
9 [SqlType("nvarchar(50)")]
10 string Name
11 {
12 get;
13 set;
14 }
15
16 [SqlType("nvarchar(250)")]
17 string Description
18 {
19 get;
20 set;
21 }
22
23 [FkQuery("ParentID", Contained = true, LazyLoad = true)]
24 Setting Setting { get;set; }
25
26 [FkReverseQuery(LazyLoad = true)]
27 [MappingName("ParentID")]
28 [SerializationIgnore]
29 Category Parent
30 {
31 get;
32 set;
33 }
34
35 [FkQuery("Parent", OrderBy = "{Name} DESC", LazyLoad = true)]
36 Category[] Childs
37 {
38 get;
39 set;
40 }
41
42 [FkQuery("Category", OrderBy = "{ID} DESC", Contained = true, LazyLoad = true)]
43 [SerializationIgnore]
44 Content[] Contents
45 {
46 get;
47 set;
48 }
49
50 int Sort
51 {
52 get;
53 set;
54 }
55
56 [FkReverseQuery(LazyLoad = true)]
57 User User
58 {
59 get;
60 set;
61 }
62
63 [FkReverseQuery(LazyLoad = true)]
64 Group Group
65 {
66 get;
67 set;
68 }
69
70 bool Visible
71 {
72 get;
73 set;
74 }
75 }
1public interface Category : Entity
2 {
3 [PrimaryKey]
4 int ID
5 {
6 get;
7 }
8
9 [SqlType("nvarchar(50)")]
10 string Name
11 {
12 get;
13 set;
14 }
15
16 [SqlType("nvarchar(250)")]
17 string Description
18 {
19 get;
20 set;
21 }
22
23 [FkQuery("ParentID", Contained = true, LazyLoad = true)]
24 Setting Setting { get;set; }
25
26 [FkReverseQuery(LazyLoad = true)]
27 [MappingName("ParentID")]
28 [SerializationIgnore]
29 Category Parent
30 {
31 get;
32 set;
33 }
34
35 [FkQuery("Parent", OrderBy = "{Name} DESC", LazyLoad = true)]
36 Category[] Childs
37 {
38 get;
39 set;
40 }
41
42 [FkQuery("Category", OrderBy = "{ID} DESC", Contained = true, LazyLoad = true)]
43 [SerializationIgnore]
44 Content[] Contents
45 {
46 get;
47 set;
48 }
49
50 int Sort
51 {
52 get;
53 set;
54 }
55
56 [FkReverseQuery(LazyLoad = true)]
57 User User
58 {
59 get;
60 set;
61 }
62
63 [FkReverseQuery(LazyLoad = true)]
64 Group Group
65 {
66 get;
67 set;
68 }
69
70 bool Visible
71 {
72 get;
73 set;
74 }
75 }
而每个表对应的实体是通过NBear创建的,如果在绑定GirdView时,使用Content[]来做DataSource,再通过强类型来获得Content.User和Content.Category,这样每次都会进行两次查询,如果绑定的列有N条,再绑定一个GirdView的总查询次数将为2N+1。
例如:
1 this.GridView1.DataSource = gateway.GetPageSelector<Content>(Content._.CategoryID == categoryID, orderBy, pageSize).FindPage(pageNo);
2 this.GridView1.DataBind();
在GirdView1中设置编定列,譬如Content.User.Name:2 this.GridView1.DataBind();
1<%# StrongTyped<Entities.User>(Container.DataItem).User.Name %>
会发现,每次绑定一行时都会进行一次Select查询。分页大小越大,查询的次数则越多。而通常我们需要使用多数据表中的数据项时,通常都是使用视图的,而NBear强大的支持从视图生成实体的功能,这样,可以轻而易举地解决这类问题,并且将查询次数减到最少。
1.首先,先建立关联三个表项的视图。结合上面的实体定义的SQL视图脚本如下:
SQL视图脚本
1if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[v_Content]') and OBJECTPROPERTY(id, N'IsView') = 1)
2drop view [dbo].[v_Content]
3GO
4
5CREATE VIEW [v_Content]
6AS
7SELECT [Category].[Name] AS [CategoryName], [Category].[Sort] AS [CategorySort],
8[Category].[Visible] AS [CategoryVisible], [Category].[Description] AS [CategoryDescription],
9[Category].[ParentID] AS [CategoryParentID],
10[Category].[User_ID] AS [CategoryUserID], [Category].[Group_ID] AS [CategoryGroupID],
11[Content].[ID], [Content].[Category_ID], [Content].[ModifiedDate],
12[Content].[UserID], [Content].[Title], [Content].[Body], [Content].[Summary],
13[Content].[Link], [Content].[TopSort], [Content].[Visible],
14[Content].[Hits], [Content].[IP], [Content].[AllowComment], [Content].[CommentCount],
15[User].[Name] AS [UserName], [User].[Email] AS [UserEmail], [User].[Status] AS [UserStatus],
16[User].[LogOnName] AS [UserLogOnName]
17FROM [Content] INNER JOIN [Category] ON [Category].[ID] = [Content].[Category_ID]
18INNER JOIN [User] ON [User].[ID] = [Content].[UserID]
19GO
1if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[v_Content]') and OBJECTPROPERTY(id, N'IsView') = 1)
2drop view [dbo].[v_Content]
3GO
4
5CREATE VIEW [v_Content]
6AS
7SELECT [Category].[Name] AS [CategoryName], [Category].[Sort] AS [CategorySort],
8[Category].[Visible] AS [CategoryVisible], [Category].[Description] AS [CategoryDescription],
9[Category].[ParentID] AS [CategoryParentID],
10[Category].[User_ID] AS [CategoryUserID], [Category].[Group_ID] AS [CategoryGroupID],
11[Content].[ID], [Content].[Category_ID], [Content].[ModifiedDate],
12[Content].[UserID], [Content].[Title], [Content].[Body], [Content].[Summary],
13[Content].[Link], [Content].[TopSort], [Content].[Visible],
14[Content].[Hits], [Content].[IP], [Content].[AllowComment], [Content].[CommentCount],
15[User].[Name] AS [UserName], [User].[Email] AS [UserEmail], [User].[Status] AS [UserStatus],
16[User].[LogOnName] AS [UserLogOnName]
17FROM [Content] INNER JOIN [Category] ON [Category].[ID] = [Content].[Category_ID]
18INNER JOIN [User] ON [User].[ID] = [Content].[UserID]
19GO
2.使用NBear.Tools.DbToEntityDesign.exe工具从数据库中生成实体定义代码:
ContentView.cs
1[ReadOnly]
2 [MappingName("v_Content")]
3 public interface ContentView : Entity
4 {
5 [SqlType("nvarchar(50)")]
6 string CategoryName { get; }
7
8 int CategorySort { get; }
9
10 bool CategoryVisible { get; }
11
12 [SqlType("nvarchar(250)")]
13 string CategoryDescription { get; }
14
15 int CategoryParentID { get; }
16
17 int CategoryUserID { get; }
18
19 int CategoryGroupID { get; }
20
21 int ID { get; }
22
23 [MappingName("Category_ID")]
24 int CategoryID { get; }
25
26 DateTime ModifiedDate { get; }
27
28 int UserID { get; }
29
30 [SqlType("nvarchar(100)")]
31 string Title { get; }
32
33 [SqlType("ntext")]
34 string Summary { get; }
35
36 [SqlType("nvarchar(250)")]
37 string Link { get; }
38
39 int TopSort { get; }
40
41 bool Visible { get; }
42
43 int Hits { get; }
44
45 [SqlType("nvarchar(50)")]
46 string IP { get; }
47
48 bool AllowComment { get; }
49
50 int CommentCount { get; }
51
52 [SqlType("ntext")]
53 string UserName { get; }
54
55 [SqlType("nvarchar(50)")]
56 string UserEmail { get; }
57
58 int UserStatus { get; }
59
60 [SqlType("nvarchar(50)")]
61 string UserLogOnName { get; }
62 }
1[ReadOnly]
2 [MappingName("v_Content")]
3 public interface ContentView : Entity
4 {
5 [SqlType("nvarchar(50)")]
6 string CategoryName { get; }
7
8 int CategorySort { get; }
9
10 bool CategoryVisible { get; }
11
12 [SqlType("nvarchar(250)")]
13 string CategoryDescription { get; }
14
15 int CategoryParentID { get; }
16
17 int CategoryUserID { get; }
18
19 int CategoryGroupID { get; }
20
21 int ID { get; }
22
23 [MappingName("Category_ID")]
24 int CategoryID { get; }
25
26 DateTime ModifiedDate { get; }
27
28 int UserID { get; }
29
30 [SqlType("nvarchar(100)")]
31 string Title { get; }
32
33 [SqlType("ntext")]
34 string Summary { get; }
35
36 [SqlType("nvarchar(250)")]
37 string Link { get; }
38
39 int TopSort { get; }
40
41 bool Visible { get; }
42
43 int Hits { get; }
44
45 [SqlType("nvarchar(50)")]
46 string IP { get; }
47
48 bool AllowComment { get; }
49
50 int CommentCount { get; }
51
52 [SqlType("ntext")]
53 string UserName { get; }
54
55 [SqlType("nvarchar(50)")]
56 string UserEmail { get; }
57
58 int UserStatus { get; }
59
60 [SqlType("nvarchar(50)")]
61 string UserLogOnName { get; }
62 }
3.使用ContentView[]绑定到GirdView即可一次获取所要的结果。