简体   繁体   中英

Entity Framework: object returns with an empty list at first, but then suddenly the list is populated correctly

I have the following class:

public class User
{
   public int Id { get; set; }
   public List<User> Connections { get; set; }

   //other properties

   public User()
   {
    Connections = new List<User>();
   }
}

Then I have a DataContext class for storage:

 public class DataContext : DbContext
 {
     public DataContext() { }

     public DataContext(DbContextOptions<DataContext> options) : base(options) { }

     public virtual DbSet<User> Users { get; set; }
 }

And a UserService class:

public class UserService: IUserService
{
   private DataContext _context;

   public UserService(DataContext context)
   {
      _context = context;
   }

   public User GetById(int id)
   {
      return _context.Users.Find(id);
   }
   ...
}

Now suppose I correctly stored 2 users, and I add each other to their respective connection lists.

The problem is in the following piece of code:

var user1 = _userService.GetById(userId);

 ---> Here user1.Connections is an empty list (unexpected)

var results = anotherList.Select(x=> 
{

   ---> Here user1.Connections have one object inside (the other user as expected)

});

I thought it was because the List was not populated yet since it was never accessed yet, but I also have a problem with the following endpoint in a controller:

var userId = int.Parse(User.Identity.Name);

var user1 = _userService.GetById(userId);

var connectionsInfo = user1.Connections.Select(x => new
{
   Id = x.Id,
   //map other properties
});

return Ok(connectionsInfo);
//this time an empty list is returned in the response, instead of a list with a single object

I read it might be regarding circular dependency, but I don't get any exception.

Also, I do not understand why in one case the list is populated after and in the other case is not populated at all.

Any idea what could be causing this?

Also I do not understand why in one case the list is populated after and in the other case is not populated at all.

It's the Lazy Loading feature in the entity framework. Lazy loading means delaying the loading of related data until you specifically request for it. For more explanation and a deep dive, you can review this good article .

Entity Framework supports three ways to load related data - eager loading, lazy loading, and explicit loading. for your scenario, It would prefer to use eager loading way. for achieving this goal EF has the Include() method. so, you can update your GetById method as below:

public User GetById(int id)
{
   return _context.Users
             .Include(item => item.Connections)
             .Find(id);
}

With the above query when you find a specific user, its connections loads at the same time too. good luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM