PS:使用默认的SQL Server 2000做数据库。
1.IsBatchUpdate =true | false 的区别
该属性设置是否进行批查询;默认值是true。
例如示例中的这段代码:
1
user.Birthday
=
DateTime.Now;
2
user.Profile.ProfileContent
=
"
modified profile content
"
;
3
user.Phones[
0
].Description
=
"
modified phone desc for home
"
;
4
user.Phones[
1
].Description
=
"
modified phone desc for work
"
;
5
6
//
now, because the user is saved before, most real operations are update, insert or update are all transparent to us. we can always easily SAVE them.
7
//
see runtime log for details and compare to those with the first time save.
8
WriteLine(
string
.Empty);
9
WriteLine(
"
Second Time Save:
"
);
10
WriteLine(
string
.Empty);
11
gateway.Save
<
LocalUser
>
(user);
IsBatchUpdate=false 的运行时逻辑:
Second Time
Save
:
Text
DELETE
FROM
[
LocalUserPhone
]
WHERE
[
ID
]
=
@ID_c011657ac5d44566b5c50774d96adf32
Parameters:
@ID_c011657ac5d44566b5c50774d96adf32
[
Guid
]
=
fb08c10f
-
f609
-
4876
-
bc7b
-
dacb3f0b4b8b
Text
DELETE
FROM
[
LocalUserPhone
]
WHERE
[
ID
]
=
@ID_955848d34eae423cbf198a7ca1228d83
Parameters:
@ID_955848d34eae423cbf198a7ca1228d83
[
Guid
]
=
aae9c0a9
-
9cbc
-
4ba3
-
a0ea
-
6b5528c85643
Text
UPDATE
[
User
]
SET
[
Birthday
]
=
@Birthday
WHERE
[
ID
]
=
@ID_04563787eaaf48a8aa0a7afc165170a8
Parameters:
@Birthday
[
DateTime
]
=
2006
-
11
-
11
1
:
49
:
47
@ID_04563787eaaf48a8aa0a7afc165170a8
[
Guid
]
=
7905c005
-
6192
-
4887
-
b7ac
-
886a7b045551
Text
UPDATE
[
LocalUserPhone
]
SET
[
Description
]
=
@Description
WHERE
[
ID
]
=
@ID_bc32d84ff6324b35b8e15a012ab0e71c
Parameters:
@Description
[
String
]
=
modified phone
desc
for
home
@ID_bc32d84ff6324b35b8e15a012ab0e71c
[
Guid
]
=
aae9c0a9
-
9cbc
-
4ba3
-
a0ea
-
6b5528c85643
Text
UPDATE
[
LocalUserPhone
]
SET
[
Description
]
=
@Description
WHERE
[
ID
]
=
@ID_8847b6d4bb3d4d90b92b2e963c0aebb5
Parameters:
@Description
[
String
]
=
modified phone
desc
for
work
@ID_8847b6d4bb3d4d90b92b2e963c0aebb5
[
Guid
]
=
fb08c10f
-
f609
-
4876
-
bc7b
-
dacb3f0b4b8b
Text
UPDATE
[
UserProfile
]
SET
[
ProfileContent
]
=
@ProfileContent
WHERE
[
ID
]
=
@ID_689ed0c5defc4ae0b7380674e4477bf3
Parameters:
@ProfileContent
[
String
]
=
modified profile content
@ID_689ed0c5defc4ae0b7380674e4477bf3
[
Guid
]
=
7b3185c0
-
c216
-
4cd0
-
aef9
-
c3fe97a57841
显然,每个操作都是单独进行一次数据库操作的。
接着看IsBatchUpdate=false的运行时逻辑:
Second Time
Save
:
Text
DELETE
FROM
[
LocalUserPhone
]
WHERE
[
ID
]
=
'
5cefdd4f-c9d6-4faf-85cd-6cc82471c8f7
'
;
DELETE
FROM
[
LocalUserPhone
]
WHERE
[
ID
]
=
'
3286192d-ab59-4bc0-a196-53e6d19fe86e
'
;
UPDATE
[
User
]
SET
[
Birthday
]
=
'
2006-11-11 1:57:39
'
WHERE
[
ID
]
=
'
d9394b00-20cf-4201-8be6-3c7da70b1f13
'
;
UPDATE
[
LocalUserPhone
]
SET
[
Description
]
=
N
'
modified phone desc for home
'
WHERE
[
ID
]
=
'
3286192d-ab59-4bc0-a196-53e6d19fe86e
'
;
UPDATE
[
LocalUserPhone
]
SET
[
Description
]
=
N
'
modified phone desc for work
'
WHERE
[
ID
]
=
'
5cefdd4f-c9d6-4faf-85cd-6cc82471c8f7
'
;
UPDATE
[
UserProfile
]
SET
[
ProfileContent
]
=
N
'
modified profile content
'
WHERE
[
ID
]
=
'
a3235692-0b60-457e-a0c5-81d276482237
'
;
全部操作都在一次数据库操作中完成。
这里有个疑问,更新UserPhone为什么要先删除原先的UserPhone呢?记录删除了,还能更新?
PS:在V3.2.1的更新中已经修改此Bug.
2.关联删除
示例中的这段删除代码:
1
WriteLine(
string
.Empty);
2
WriteLine(
"
Then Delete:
"
);
3
WriteLine(
string
.Empty);
4
gateway.Delete
<
LocalUser
>
(user);
运行时逻辑:
Then
Delete
:
Text
SELECT
[
ID
]
,
[
ProfileContent
]
,
[
UserID
]
FROM
[
UserProfile
]
WHERE
[
UserID
]
=
@ID
Parameters:
@ID
[
Guid
]
=
8956d9c4
-
fc3c
-
469a
-
8e9c
-
57c645fe69e2
Text
SELECT
[
ID
]
,
[
Description
]
,
[
Number
]
,
[
UserID
]
FROM
[
LocalUserPhone
]
WHERE
[
UserID
]
=
@ID
Parameters:
@ID
[
Guid
]
=
8956d9c4
-
fc3c
-
469a
-
8e9c
-
57c645fe69e2
Text
DELETE
FROM
[
UserProfile
]
WHERE
[
ID
]
=
'
bbbb863e-6998-48b2-9764-9b0504cbbd03
'
;
DELETE
FROM
[
LocalUserPhone
]
WHERE
[
ID
]
=
'
93db36c5-8bfe-4d14-9e76-6f54e40c7708
'
;
DELETE
FROM
[
LocalUserPhone
]
WHERE
[
ID
]
=
'
0114dd84-7ab2-4a80-ada1-e581bf849a1c
'
;
DELETE
FROM
[
User
]
WHERE
[
ID
]
=
'
8956d9c4-fc3c-469a-8e9c-57c645fe69e2
'
;
DELETE
FROM
[
LocalUser
]
WHERE
[
ID
]
=
'
8956d9c4-fc3c-469a-8e9c-57c645fe69e2
'
;
由于UserPhone和UserProfile都设置了Contained,所以在删除User同时,也会删除它们。而Groups没有设置Contained,所以不会执行同步更新与删除操作。
这里的前两个Select查询,应该是因为LazyLoad=true,在进行删除操作时才第一次使用到UserPhone和UserProfile,所以就会就行Select查询获取它们。
3.Relation属性
User和Group的一对多关系是通过UserGroup来实现的,示例中的代码:
1
[Relation]
2
public
interface
UserGroup : NBear.Common.Design.Entity
3
{
4 [RelationKey(typeof(User), "ID")]
5 Guid UserID
6 {
7 get;
8 set;
9 }
10
11 [RelationKey(typeof(Group), "ID")]
12 Guid GroupID
13 {
14 get;
15 set;
16 }
17 }
User中的Groups属性代码:
1
[Query(RelationType
=
typeof
(UserGroup), OrderBy
=
"
{Name} DESC
"
, LazyLoad
=
true
)]
2
Group[] Groups
3
{
4 get;
5 set;
6}
设置了LazyLoad=true,和RelationType。
先来看看这段代码:
WriteLine(
string
.Empty);
WriteLine(
"
Find the saved local user as user:
"
);
WriteLine(
string
.Empty);
User user
=
gateway.Find
<
User
>
(localUser.ID);
WriteLine(
"
The found user:
"
);
WriteLine(SerializationManager.Serialize(user));
运行逻辑:
Find the saved local
user
as
user
:
Text
SELECT
[
ID
]
,
[
Name
]
,
[
Status
]
,
[
Birthday
]
FROM
[
User
]
WHERE
[
ID
]
=
@ID_f7b6527dbe0443efb1e4c169ed05565e
Parameters:
@ID_f7b6527dbe0443efb1e4c169ed05565e
[
Guid
]
=
eaea2eb0
-
a039
-
45a4
-
958f
-
610521863f71
Text
SELECT
[
ID
]
,
[
ProfileContent
]
,
[
UserID
]
FROM
[
UserProfile
]
WHERE
[
UserID
]
=
@ID
Parameters:
@ID
[
Guid
]
=
eaea2eb0
-
a039
-
45a4
-
958f
-
610521863f71
The found
user
:
Text
SELECT
[
ID
]
,
[
Name
]
,
[
ParentID
]
FROM
[
v_Group_UserGroup
]
WHERE
[
UserGroup_UserID
]
=
@UserGroup_UserID_369b513a1ebd4c2dbf7b6e2ca8bf546a
ORDER
BY
[
Name
]
DESC
Parameters:
@UserGroup_UserID_369b513a1ebd4c2dbf7b6e2ca8bf546a
[
Guid
]
=
eaea2eb0
-
a039
-
45a4
-
958f
-
610521863f71
<
?xml version
=
"
1.0
" encoding
=
"utf
-
16
"?
>
<
User
xmlns:xsi
=
"http:
//
www.w3.org
/
2001
/
XMLSchema
-
instance" xmlns:xsd
=
"http:
//
www.w3.org
/
2001
/
XMLSchema"
>
<
ID
>
eaea2eb0
-
a039
-
45a4
-
958f
-
610521863f71
</
ID
>
<
Name
>
<
FirstName
>
teddy
</
FirstName
>
<
LastName
>
ma
</
LastName
>
</
Name
>
<
Profile
>
<
ID
>
117f29ab
-
baa6
-
4500
-
a670
-
c27160394397
</
ID
>
<
ProfileContent
>some
sample content
</
ProfileContent
>
<
UserID
>
eaea2eb0
-
a039
-
45a4
-
958f
-
610521863f71
</
UserID
>
</
Profile
>
<
Groups
/>
<
Status
>
Available
</
Status
>
<
Birthday xsi:nil
=
"true"
/>
</
User
>
第三次的Select查询,是通过查询视图v_Group_UserGroup来获取Groups的。为什么是使用视图来填充的呢?估计这应该就是UserGroup设置了Relation的缘故。比较User和UserPhones的一对多关联,就可以知道。
对
于我目前只能使用Access作数据库的,不支持视图,所以不应该使用类似UserGroup这类关联
。
Access同样支持视图查询的。(不知道分析对不对?为了对比在Sql Server和Access中的不同,将会在以后更新中插入对使用Access的分析。)
估计这个Select查询,又是因为LazyLoad的缘故。因为SerializationManager.Serialize(user)操作需要用到Groups属性。
做个测试证明上面的说法,在下Find()之前加上一句判断操作:
if
(localUser.Groups
==
null
) ;
WriteLine(
string
.Empty);
WriteLine(
"
Find the saved local user as user:
"
);
WriteLine(
string
.Empty);
User user
=
gateway.Find
<
User
>
(localUser.ID);
WriteLine(
"
The found user:
"
);
WriteLine(SerializationManager.Serialize(user));
运行时逻辑:
Text
SELECT
[
ID
]
,
[
Name
]
,
[
ParentID
]
FROM
[
v_Group_UserGroup
]
WHERE
[
UserGroup_UserID
]
=
@UserGroup_UserID_457cecc48982406fac4bb2726d8af8ce
ORDER
BY
[
Name
]
DESC
Parameters:
@UserGroup_UserID_457cecc48982406fac4bb2726d8af8ce
[
Guid
]
=
eaea2eb0
-
a039
-
45a4
-
958f
-
610521863f71
Find the saved local
user
as
user
:
看,这个多出来的Select查询再次说明了LazyLoad。
发现结果中好像少了一样,就是UserPhone。在下一篇后续分析中,将会对比FindArray()的运行时逻辑,来看看究竟错误发生在哪里
。
呵呵,完全是自己不够细心,在Teddy指引下,这里只是Find<User>(),所以是不会有UserPhone的。
今晚暂时到此。。。。
如果大家发现了错误,请即时留言更正,因为小弟才刚刚接触NBear不久,正在努力学习中.......