Lazy loading/change tracking with no reflection, stateful navigation

5 posts, 1 answers
  1. nagir
    nagir avatar
    161 posts
    Member since:
    Feb 2007

    Posted 26 May 2009 Link to this post

    Hi,
    Just wondering how is it possible to do lazy loading and change tracking without using reflection. How OA technically achieves this.

    Another questions is if following tests will pass in OA:

    public void AddingPostAssignsBlog() { 
      Blog b = new Blog(); 
      Post p1 = new Post(); 
      Post p2 = new Post(); 
     
      b.Posts.Add(p1); // Not this: b.AddPost(p1) 
      b.Posts.Add(p2); 
     
      Assert.AreSame(b, p1.Blog); 
      Assert.AreSame(b, p2.Blog); 
     
    public void AddingBlogAssignsPost() { 
      Blog b = new Blog(); 
      Post p1 = new Post(); 
      Post p2 = new Post(); 
     
      p1.Blog = b; 
      p2.Blog = b; 
     
      Assert.AreEqual(2, b.Posts.Count); 
    }  


    Additionally how OA will behave in this scenario:
    Blog b1 = new Blog(); 
    Blog p2 = new Blog(); 
    Post p = new Post(); 
    p.Blog = b1; // p is in b1 
    b2.Posts.Add(b); // b is in b2!!  






    Thanks,
    Dmitriy.
  2. nagir
    nagir avatar
    161 posts
    Member since:
    Feb 2007

    Posted 28 May 2009 Link to this post

    Anybody?
  3. DevCraft banner
  4. Zoran
    Admin
    Zoran avatar
    534 posts

    Posted 29 May 2009 Link to this post

    Hello Dmitriy,

    OpenAccess uses the a code-injection mechanism called enhancement to inject code in assemblies containing persistent classes. You can see that if you open an enhanced assembly with the reflector. That cares about all functionality like lazy-loading change-tracking caching etc..

    Regarding your second question, the first test would not pass the Assert because your persistent objects do not have any relationship to an object scope. Also you should have set the manage collection functionality of the Blog.Posts collection to true so that the scope can resolve the references. Here is a sample how the test would pass:
    using (IObjectScope scope = ObjectScopeProvider1.GetNewObjectScope()) 
       scope.Transaction.Begin(); 
       Blog b = new Blog(); 
       scope.Add(b); 
       Post p1 = new Post(); 
       Post p2 = new Post(); 
       b.Posts.Add(p1); //The references are resolved by the object scope here and  
       b.Posts.Add(p2); //here in case you have a managed collection 
       Assert.AreSame(b, p1.Blog);  
       Assert.AreSame(b, p2.Blog);  
       scope.Transaction.Commit(); //Here you can call Rollback as well 
     
     

    The second test would not pass because the collection of the blog is not calculated before you push the Post objects on the server. Here is how the working code could look:
    using (IObjectScope scope = ObjectScopeProvider1.GetNewObjectScope()) 
        scope.Transaction.Begin(); 
        Blog b = new Blog();  
        Post p1 = new Post();  
        Post p2 = new Post();  
     
        p1.Blog = b;  
        p2.Blog = b;  
        scope.Add(p1);     
        scope.Add(p2); 
        scope.Transaction.Commit(); 
     
        scope.Transaction.Begin();  
        Assert.AreEqual(2, b.Posts.Count); //Here because we are in a new transaction the collction of "b" is recalculated 
        scope.Transaction.Rollback(); 

    When you have a case like the third one - the behavior is the following: when you say p.Blog = b1  - p has reference to b1, but b1.Posts collection is not updated - that would happen after you commit a transaction and then access b1.
    After you execute b2.Posts.Add(p) - p is added to the b2.Posts collection but it still has the reference p.Blog==b1;

    If you add these objects in the database though, p will be associated with b2 - the blog whose collection was altered in case you have switched manage collection to true. If manage collection is turned off for the posts collection - p will be inserted with a reference to the b1 Blog.

    I hope this makes work with OpenAccess more clear for you.

    Best wishes,
    Zoran
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
  5. nagir
    nagir avatar
    161 posts
    Member since:
    Feb 2007

    Posted 29 May 2009 Link to this post

    Hi Zoran,

    Thanks a lot. It's not clear.

    One more question. You say that OpenAccess uses the a code-injection mechanism called enhancement to inject code in assemblies containing persistent classes.

    I have just had a look at the samples and do not see any post-build actions defined in projects (I see only ProjectExtensions/UserProperties in a .csproj file).
    So how and at what stage the assembly gets injected?

    Thanks,
    Dmitriy.
  6. Answer
    Zoran
    Admin
    Zoran avatar
    534 posts

    Posted 29 May 2009 Link to this post

    Hello Dmitriy,

    When you enable a project to use OpenAccess the entries you have seen in the .csproj files are inserted. The project after that has some properties added one of which  is "Enhancing". If "Enhancing" is enabled, which is the default, the enhancer code is injected on compilation. You can not see the injected code in .csproj or other project files, but only in the already compiled assembly. Open the compiled assembly with .NET Reflector and you can see the code by the enhancer.


    All the best,
    Zoran
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
Back to Top
DevCraft banner