Search code examples
c#entity-frameworkasp.net-coreentity-framework-coreasp.net-core-identity

Loading custom ApplicationUser object from database


I am using ASP.NET Core 2.0 with Identity and Entity Framework. I have extended the IdentityUser class into the ApplicationUser below:

namespace TxTools.Data.Features.Shared.Models
{
    public class ApplicationUser : IdentityUser
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }
        [ForeignKey("PhotoResourceId")]
        public BlobResource Photo { get; set; }
    }
}

Here is my BlobResource:

namespace TxTools.Data.Features.BlobStorage.Models
{
    public class BlobResource
    {
        [Key]
        public Guid ResourceId { get; protected set; }
        public string Container { get; protected set; }
        public string MimeType { get; protected set; }
        public string Filename => String.Format("{0}.{1}", ResourceId, MimeTypes.GetExtension(MimeType));
        public BlobResource(string container, string mimeType)
        {
            this.ResourceId = Guid.NewGuid();
            this.Container = container;
            this.MimeType = mimeType;
        }
    }
}

Entity Framework saves the BlobResource when I add it to the ApplicationUser, but I cannot get it to load the BlobResource from the database. The object is always null. I have tried several Fluent API commands to try and get it to load, but none work.


Solution

  • Firstly, the User and BlobResource classes need references to one another. You need to decide whether the relation is one-to-one (one user one photo), one-to-many (one user many photos, or many users one photo) or many-to-many.

    Entity Framework's way of describing relationships is here: https://learn.microsoft.com/en-us/ef/core/modeling/relationships

    Secondly, EF is lazy-loading so you have to tell it to chase these relations when you load users from the database. Assuming you have a DB context class that extends IdentityDbContext...

    public class MyContext: IdentityDbContext<ApplicationUser>
    {
        public DbSet<ApplicationUser> Users { get; set; }
        public DbSet<BlobResource> BlobResources { get; set; }
    }
    

    ... you would use Include as follows:

    var usersWithBlobs = myContext.Users.Include(user => user.Photo);
    

    or a specific user given its id:

    var myUser = myContext.Users.Where(u => u.Id == id).Include(user => user.Photo);
    

    Loading is described here: https://learn.microsoft.com/en-us/ef/core/querying/related-data