locked
Issue with Navigation properties Load RRS feed

  • Question

  • Hi,

    Issue: Could not "reload" a navigation properties via the load function

    Case:

    I have an entity A that have a "many to many" navigation property B that have a "many to many" navigation property C.

    I have one and only one entity context and lazyloading is set to true and I'm using a Poco T4.

    A is loaded via query so I have always the database value.

    Sadly when you load A the second time, EF is loading the nav properties from its cache (Object Graph, I think this is the right term).

    So I use context.Entry(MyEntity).Collection(o=>o.BnavigationProperties).Load(); which reload properly the B collection from the database.

    As I have the same issue with C, I decide to "load" it in the same way, but unfortunatly, this doesn't work.

    If someone have any tips or way to fix this, I will appreciate that. 

    FYI: I looked at http://msdn.microsoft.com/en-US/data/jj574232 for entity loading but no answer on navigation of navigation. :D

    Thanks,


    • Edited by MDSInfo Friday, September 21, 2012 8:19 AM
    Friday, September 21, 2012 8:12 AM

All replies

  • Hi MDSInfo,

    Welcome to MSDN Forum.

    I wrote a demo to demonstrate how to add navigation property of a navigation property. Please refer to it.

    TestA : TestB - n : n

    TestB : TestC - n : n

    static void Main(string[] args)
            {
                using (TestEntities context = new TestEntities())
                {
                    var query = (from a in context.TestAs.Include("TestBs.TestCs") select a).ToList();
                    
                }
            }

    The code above can help you load both the TestB and TestC.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Monday, September 24, 2012 2:28 AM
  • Hi,

    thanks for the code.

    In my case, I should not use this for performance reason.

    In fact, I choose to use a lazyloading approach rather than eager loading. 

    My list of A can be huge, so I don't want to retrieve all those data for each iteration as the user may just use 1 or 2.

    In your sample, if you use lazyloading, does it works?

    Steps to reproduce my bug:

    1 - Load A

    2- Load B and then Load C

    3-  in the database only : Add a C in B list and Add a B in the A list

    4 - Load A again 

    5 - Try to refresh B & C to get the database updated list.

    In my case, I can retrieve the B's list correctly but not the C one.

    Thanks,

    FYI, I'm on EF 5.

    Monday, September 24, 2012 4:03 PM
  • Hi MDSInfo,

    I don't think Context should load C. In your 3rd step, add C and B in the database only, EF knows nothing about it. Later, you load A, I'm not sure if you also load navigation property by 'include' or explicitly loading, if you do, the B can be captured by EF, but EF still know nothing about C. Could you please post some code about how you load the entities? This is, so I can help you more effectively.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Tuesday, September 25, 2012 1:55 AM
  • Hi,

    To load A, I use a query without any include.

    Then to load B, I use: context.Entry(ATypeEntity).Collection(o=>o.BnavigationProperties).Load(); 

    Then to load C, I usecontext.Entry(BTypeEntity).Collection(o=>o.CnavigationProperties).Load();  

    On the first load everything is working fine.

    Then I change my database (to simulate a change made by another user).

    I reload A with a Query so all the properties are retrieved from the database.

    Then to refresh the context for B's list, I use context.Entry(ATypeEntity).Collection(o=>o.BnavigationProperties).Load(); as if I use the standard lazyloading it will only retrieve the data from the context. By Using Load, all the data should be retrieved from the database (as per the MSDN Documentation). 

    For B's list, it's working, I can get the updated list.

    Then to refresh the context C's list, I use context.Entry(BTypeEntity).Collection(o=>o.CnavigationProperties).Load(); Same approach as the previous step. But for any reason, this is not working and EF only retrieve the data from the context and not the database.

    I hope this helps to reproduce my issue and you will be able to give me some hint.

    Thanks,

    Tuesday, September 25, 2012 7:54 AM
  • Hi MDSInfo,

    I followed your steps and trying to repro the issue, but I successfully load 'TestCC' by the code below. Please check if the code has any difference with yours and let me know.

    static void Main(string[] args)
            {
                //There's one entity in each of the three database tables
                //testA database table: id:1 name:testA
                //testB database table: id:1 name:testB
                //testC database table: id:1 name:testC
                //testB is the navigation property of testA and testC is the navigation property of testB
                using (TestEntities context = new TestEntities())
                {
                    //Load the first entity 'testA'
                    var testA = context.TestAs.First();
    
                    //Load the navigation property of 'testA', now there's only one entity 'testB' in the collection
                    context.Entry(testA).Collection(x => x.TestBs).Load();
    
                    //Load the navigation property of every entities in testBs collection, now there's only one entity 
                    //in the collection of 'testCs' named 'testC'
                    foreach (var v in testA.TestBs)
                    {
                        context.Entry(v).Collection(x => x.TestCs).Load();
                    }
    
                    //Everything works well, I can see the 'testA' and its navigation property 'testBs' which contains one 
                    //entity 'testB' has loaded, the navigation property of 'testB' also loaded.
                    //I add a breakpoint at the close brace above, and then add a new entity 'testBB' into 'testB' table, add a 
                    //new entity 'testCC' into 'testC' table, add two records into relationship tables to create relationship between
                    //'testA' and 'testBB', 'testCC' and 'testBB', then continue run the app
    
                    //Load 'testA' again
                    testA = context.TestAs.First();
    
                    //Load the navigation property of 'testA', now there're two entities in the collection 'testB' and 'testBB'
                    context.Entry(testA).Collection(x => x.TestBs).Load();
    
                    //Load the navigation property of the two entities
                    foreach (var v in testA.TestBs)
                    {
                        context.Entry(v).Collection(x => x.TestCs).Load();
                    }
    
                    //After the code run to the end, I can find 'testCC' also been loaded from Watch Window
                }
            }

    I hope this can help.

    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Tuesday, September 25, 2012 8:37 AM
  • Hi MDSInfo,

    Have you solved the issue? I look forward to hearing from you. If you need further help, please feel free to let me know, I will be more than happy to be of assistance.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Thursday, September 27, 2012 2:11 AM
  • Hi,

    Sorry I'm away for a week, so I will post back as soon as I can on your solution.

    thanks,

    Monday, October 1, 2012 4:12 PM