Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework 6 context not retrieving navigation properties

I have found many other posts but they are nt facing exactly the same problem. And they are using a slightly different code. SO I think it is worth reviewing this.

I´m using EF6 code first, and I created a Client Entity that has some navigation properties.

I´ll post just the relevant code, consider there are a few more properties and foreign keys as well, but not relevant to the problem. Model is generating ok.

public class Client
{
    public Client()
    {
        JobsExperiences = new Collection<JobsExperience>();
        CapacitationCourses = new Collection<CapacitationCourse>();
        ScholarLevelDetails = new Collection<ScholarLevelDetail>();
        Relatives = new Collection<Relative>();
    }
    public long ClientID { get; set; }
    public virtual ICollection<ScholarLevelDetail> ScholarLevelDetails { get; set; }

    public virtual ICollection<JobsExperience> JobsExperiences { get; set; }
}

Now I created a ClientServices class where I put all methods that get or send data from and to the data base., ther I have this code, which is working randomly, I´ll try to explain clearly.

    internal Client GetClient(string userId, bool lazyLoadingEnabled = true)
    {
        using (var context = new ApplicationDbContext())
        {
            context.Configuration.LazyLoadingEnabled=lazyLoadingEnabled;

            var client = (from _client in context.Client
                          where _client.ApplicationUserId == userId
                          select _client).FirstOrDefault();

            return client;
        }
    }

My objective some cases is to retrieve just the client attributes, and sometimes all attributes including navigation properties.

In my controller I have a line like this

var client = uuc.GetClient(user.Id, false);

or this

var client = uuc.GetClient(user.Id);

When I run the first sentence, the navigation properties are initialized but all has Count=0, even when my DB has records associated. I think, if lazy loading is disabled, it means eager loading is enabled, but it seems not. However, there is no Load() Method in the navigation properties to force load.

When I run the second sentence, the navigation properties throws an exception 'client.ScholarLevelDetails' threw an exception of type 'System.ObjectDisposedException'. This is thrown one line after the sentence, loking at the navigation properties in the watch. However, and this is the weirdest part, if I step back to the sentence and debug stepping into the method, All navigation properties are loaded correctly.

Why the code behaves differently if running at once than running stepping into the method? I presume the using statement scope finishes before that the navigation properties load, but why disabling lay loading doe snot retrieve them either? How can I code this to have a consistent behaviour?

like image 654
Ricker Silva Avatar asked Feb 06 '14 15:02

Ricker Silva


1 Answers

I change the query code Ihad in Linq with this one.

    internal Client GetClient(string userId, bool lazyLoadingEnabled = true)
    {
        using (var context = new ApplicationDbContext())
        {
            context.Configuration.LazyLoadingEnabled = lazyLoadingEnabled;

            var client = context
                        .Client
                        .Include(s => s.ScholarLevelDetails)
                        .Include(s => s.JobsExperiences)
                        .Include(s => s.CapacitationCourses)
                        .Include(s => s.Relatives)
                        .FirstOrDefault(s => s.ApplicationUserId == userId);

            return client;
        }
    }

And now it works. however I still have some questions I´d lve to discuss with you readers and colleagues.

Why plain Linq doesn´t work? Why it doesn matter if lazyloading is enabled or not, this code works the same everytime?

like image 51
Ricker Silva Avatar answered Nov 09 '22 17:11

Ricker Silva