I get error: Value cannot be null, Why is my ICollection always null?

asp.net asp.net-core c# entity-framework-core

Question

this is OrganizationPhoto module

public class OrganizationPhoto
{
    public int Id { get; set; }
    public string Url { get; set; }
    public string Description { get; set; }
    public DateTime DateAdded { get; set; }
    public bool IsMain { get; set; }
    public string PublicID { get; set; }
    public Organization Organization { get; set; }
    public int OrganizationId { get; set; }
}

this is organization module

public class Organization
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public DateTime DateCreated { get; set; }
    public string PublicID { get; set; }
    public User User { get; set; }
    public int UserId { get; set; }
    public ICollection<OrganizationPhoto> OrganizationPhotos { get; set; }
    public ICollection<OrganizationHeadPhoto> OrganizationHeadPhotos { get; set; }
}

i map OrganizationPhoto in automapper with dtos

        CreateMap<OrganizationPhoto, PhotosForDetailedDto>();
        CreateMap<OrganizationPhoto, PhotoForReturnDto>();
        CreateMap<PhotoForCreationDto, OrganizationPhoto>();

then i get organization by id like this:

Task<Organization> GetOrganizationById(int id);

and

    public async Task<Organization> GetOrganizationById(int id)
    {
        var organization = await _context.Organizations.FirstOrDefaultAsync(p => p.Id == id);
        return organization;
    }

and then i try get values from ICollection OrganizationPhotos, but it is null see image

1
1
11/5/2019 6:52:23 AM

Accepted Answer

EF never loads related entities by default. You must either eagerly or explicitly load the relationships, or set up lazy loading. The best method is to eager load, as that will then do everything in one query with appropriate joins:

 var organization = await _context.Organizations
     .Include(x => x.OrganizationPhotos)
     .Include(x => x.OrganizationHeadPhotos)
     .FirstOrDefaultAsync(p => p.Id == id);

If there's sub-relationships you also need loaded, you may need to use ThenInclude as well:

.Include(x => x.OrganizationPhotos)
    .ThenInclude(x => x.SomeOtherRelationship)

You should avoid lazy-loading as it's far too easy to hammer your database, if you're not paying attention to what you're doing, but if you want them "automatically" loaded then you first need to make the properties virtual:

public virtual ICollection<OrganizationPhoto> OrganizationPhotos { get; set; }

And then enable lazy loading via:

services.AddDbContext<MyContext>(o =>
    o.UseSqlServer(Configuration.GetConnectionString("Foo"))
     .UseLazyLoadingProxies());
1
10/31/2019 3:45:13 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow