简体   繁体   中英

Why is my Custom Object Property in ApplicationUser null?

I have created a custom class called Person to store name, address, etc. This class/model is cross-referenced from other models, including ApplicationUser :

public class ApplicationUser : IdentityUser
{
    public Person Person { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
}

In one of my controllers, I use the following code to get the current user logged in and get it's Person object, like so:

        var user = UserManager.FindById(User.Identity.GetUserId());
        var person = user.Person;

My Person class is also defined in the ApplicationDbContext :

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("MyContext", throwIfV1Schema: false)
    {
    }

    public DbSet<Person> People { get; set; }
}

When I inspect user , I can see that Entity Framework populated the object, because I see the user ID, email address, password hash, everything! Everything except the Person property! However, I can see in the database that the corresponding row is not null , but has the correct ID for the Person .

I'm new to ASP.NET/MVC/Entity framework and I've read that it uses lazy loading by default. Is this what I'm experiencing? If so, how do I tell Entity to use eager loading on the Person property? If not, what am I doing wrong?

This is probably a mapping problem. Entity Framework mappings are too complex for me to explain here, but I'll point out where the problem might be.

Make sure ApplicationUser has a foreign key property to Person in a way that Entity Framework can understand it. Entity Framework is convention based, so it will look for a PersonId property in your ApplicationUser class by default. If you don't want to use the default name, you could use a fluent configuration on your Context's OnModelCreating to give it a custom name.

I personally think that it's always a good idea to manually map all your relationships. Here's an example:

public void OnModelCreating(ModelBuilder modelBuilder)
{
    builder.Entity<ApplicationUser>().HasRequired(m => m.Person).HasForeignKey(d => d.Person) 
}

Please refer to this link for more information: https://msdn.microsoft.com/en-us/data/jj591620.aspx

I would make Person class inherit from IdentityUser or ApplicationUser . Then, I would have the following in the dbcontext class:

DbSet<Person> People {get;set;}

Then you can use this:

MyDbContext db = new MyDbContext();    
string userid = User.Identity.GetUserId();
var user = db.People.Single(p=>p.Id == userid );

In the entity framework code first approach the entity framework makes the first integer property as the primary key. So here you adding the reference of the Person class in the application User class. You can try this as:

[ForeignKey("PersonId")]

public virtual Person Person{get;set;}

public int PersonId{get;set;}

This will make the PersonId as the foreign key in the application User table.You can make it nullable also

public int? PersonId{get;set;}

From there you can get the Id of the Person object inserted in the application User Table and then you can get the properties of the person object.

I hope this might help you as this maps the relationship between two tables.

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