EntityFramework Explicit Loading doesn't fetch all entities

I have 2 classes (User and Device) as described below.

public class User {
    public int UserId { get; set; }
    public virtual ICollection<Device> Devices { get; set; }
    ...
}

public class Device {
    public int UserId;
    public virtual User User { get; set; }
    ...
}

      

I have a repository for each of these two objects and I have disabled lazy loading in my data context like so.

public class MyDbContext : DbContext
{
    public MyDbContext()
        : base(name=MyDbContext)
    {
        this.Configuration.LazyLoadingEnabled = false;
    }
}

      

I am trying to find all devices associated with a user account.

I tried to do it in two different ways.

Approach # 1 - Calling a Load on a User-Associated Property

using (MyDbContext dbContext = new MyDbContext())
{
    // performing some database operations ...

    var user = dbContext.Users.Find(8);

    // do some operations 

    if (user.Devices == null or user.Devices.Count() ==0)
    dbContext.Entry(user).Collection(u => u.Devices).Load();

    var devices = user.Devices;
}

      

Approach # 2 - Removing from a set of devices using where

using (MyDbContext dbContext = new MyDbContext())
{
    // performing some database operations ...

    var user = dbContext.Users.Find(8);

    // do some operations 

    if (user.Devices == null or user.Devices.Count() ==0)        
    var devices = dbContext.Devices.Where(d => d.UserId == user.UserId).ToList();
}

      

For some reason, Approach # 1 does not always retrieve all devices, however Approach # 2 retrieves all devices! Can someone please explain to me what I am doing wrong?

I started a SQL Server Profiler to see if I was doing something wrong. The queries generated by both approaches were identical. So I am really confused about what I am doing wrong!

+3


source to share


1 answer


Can someone explain to me what I am doing wrong?

I cannot explain why you are experiencing what you are experiencing, but personally I do not use Find()

and Load()

as these methods are complex in terms of how they work with the local context cache. Therefore, I would recommend the following query:

var user = dbContext.Users
  .Include(u => u.Devices);
  .FirstOrDefault(u => u.id = 8);

      

Since you're only fetching one user, no Cartesian issue . This request will populate the context with the user and all devices associated with the user in a single expression.

If you really want a separate variable with all devices afterwards:

var devices = user.Devices;

      



An important note about my answer is that since I am generally with Entity Framework in a web environment, my code is constantly creating / deleting context, so a local cache on the Entity Framework is pretty much useless. For a stateless application (Winforms / WPF) this might not be the best solution.

Updated for your comment

Is there another way to download later?

Like Brendan Green Comment you can use:

var devices = dbContext.Devices
  .Where(w => w.UserId == 8);

      

(Note that this does not execute the query against the data source).

+4


source







All Articles