ORM_Adv_Tutorial 示例的分析与学习(1)

PS:使用默认的SQL Server 2000做数据库。
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 的运行时逻辑:
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)]
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));
运行逻辑:
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不久,正在努力学习中.......

posted @ 2006-11-11 02:43  MK2  阅读(510)  评论(0编辑  收藏  举报