ORM_Adv_Tutorial 示例的分析与学习(1)
PS:使用默认的SQL Server 2000做数据库。
1.IsBatchUpdate =true | false 的区别
该属性设置是否进行批查询;默认值是true。
例如示例中的这段代码:
接着看IsBatchUpdate=false的运行时逻辑:
这里有个疑问,更新UserPhone为什么要先删除原先的UserPhone呢?记录删除了,还能更新?
PS:在V3.2.1的更新中已经修改此Bug.
2.关联删除
示例中的这段删除代码:
这里的前两个Select查询,应该是因为LazyLoad=true,在进行删除操作时才第一次使用到UserPhone和UserProfile,所以就会就行Select查询获取它们。
3.Relation属性
User和Group的一对多关系是通过UserGroup来实现的,示例中的代码:
User中的Groups属性代码:
设置了LazyLoad=true,和RelationType。
先来看看这段代码:
第三次的Select查询,是通过查询视图v_Group_UserGroup来获取Groups的。为什么是使用视图来填充的呢?估计这应该就是UserGroup设置了Relation的缘故。比较User和UserPhones的一对多关联,就可以知道。对于我目前只能使用Access作数据库的,不支持视图,所以不应该使用类似UserGroup这类关联。Access同样支持视图查询的。(不知道分析对不对?为了对比在Sql Server和Access中的不同,将会在以后更新中插入对使用Access的分析。)
估计这个Select查询,又是因为LazyLoad的缘故。因为SerializationManager.Serialize(user)操作需要用到Groups属性。
做个测试证明上面的说法,在下Find()之前加上一句判断操作:
运行时逻辑:
1.IsBatchUpdate =true | false 的区别
该属性设置是否进行批查询;默认值是true。
例如示例中的这段代码:
1user.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 的运行时逻辑: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);
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
显然,每个操作都是单独进行一次数据库操作的。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' ;
全部操作都在一次数据库操作中完成。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);
运行时逻辑: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,所以不会执行同步更新与删除操作。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' ;
这里的前两个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 }
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)]
2Group[] Groups
3{
4 get;
5 set;
6}
2Group[] 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));
运行逻辑: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>
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的一对多关联,就可以知道。
估计这个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));
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:
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不久,正在努力学习中.......