NBear学习之路1:利用视图创建多表关联的实体
若还不清楚NBear中如何实现ORM,请先阅读Teddy所写的《NBearV3 Step by Step教程——ORM篇》。
通常在一些应用中所使用到的字段不仅仅来左一个数据表,如一个文章列表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
}
![]()
User.cs
1
public 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
1
public 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。
例如:
而通常我们需要使用多数据表中的数据项时,通常都是使用视图的,而NBear强大的支持从视图生成实体的功能,这样,可以轻而易举地解决这类问题,并且将查询次数减到最少。
1.首先,先建立关联三个表项的视图。结合上面的实体定义的SQL视图脚本如下:
![]()
SQL视图脚本
1
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[v_Content]') and OBJECTPROPERTY(id, N'IsView') = 1)
2
drop view [dbo].[v_Content]
3
GO
4![]()
5
CREATE VIEW [v_Content]
6
AS
7
SELECT [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]
17
FROM [Content] INNER JOIN [Category] ON [Category].[ID] = [Content].[Category_ID]
18
INNER JOIN [User] ON [User].[ID] = [Content].[UserID]
19
GO
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
}
3.使用ContentView[]绑定到GirdView即可一次获取所要的结果。
通常在一些应用中所使用到的字段不仅仅来左一个数据表,如一个文章列表GirdView中,使用到了Content、User、Category三个表中的项。
关系图如下:



1

2



3

4

5



6

7

8

9

10

11



12

13

14

15



16

17

18

19

20

21



22

23

24

25

26

27

28

29



30

31

32

33

34

35

36



37

38

39

40

41

42

43



44

45

46

47

48

49



50

51

52

53



54

55

56

57

58

59



60

61

62

63

64

65



66

67

68

69

70

71



72

73

74

75

76

77

78



79

80

81

82

83

84



85

86

87

88

89

90



91

92

93

94

95

96

97



98

99

100

101



1

2



3

4

5



6

7

8

9

10

11



12

13

14

15

16

17

18



19

20

21

22

23

24

25



26

27

28

29

30

31

32

33



34

35

36

37

38

39

40

41



42

43

44

45

46

47

48

49



50

51

52

53

54

55

56

57



58

59

60

61

62

63

64

65



66

67

68

69

70

71

72

73



74

75

76

77

78

79



80

81

82

83

84

85

86



87

88

89

90

91

92

93



94

95

96

97

98

99

100



101

102

103

104

105

106

107



108

109

110

111

112

113

114



115

116

117

118

119

120

121



122

123

124

125

126

127

128



129

130

131

132

133

134



135

136

137

138

139

140



141

142

143

144

145

146



147

148

149

150

151

152



153

154

155

156



1

2



3

4

5



6

7

8

9

10

11



12

13

14

15

16

17

18



19

20

21

22

23

24



25

26

27

28

29

30



31

32

33

34

35

36

37



38

39

40

41

42

43

44

45



46

47

48

49

50

51



52

53

54

55

56

57

58



59

60

61

62

63

64

65



66

67

68

69

70

71



72

73

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视图脚本如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

2.使用NBear.Tools.DbToEntityDesign.exe工具从数据库中生成实体定义代码:


1

2

3

4



5

6



7

8



9

10



11

12

13



14

15



16

17



18

19



20

21



22

23

24



25

26



27

28



29

30

31



32

33

34



35

36

37



38

39



40

41



42

43



44

45

46



47

48



49

50



51

52

53



54

55

56



57

58



59

60

61



62

3.使用ContentView[]绑定到GirdView即可一次获取所要的结果。