configuring one to one relationship in asp.net identity

南楼画角 提交于 2019-12-12 02:43:27

问题


this is my ApplicationUser class.I have added only one new property ----

   public class ApplicationUser : IdentityUser
   {
    //public ApplicationUser()
    //{
    //    UserProfileInfo = new UserProfileInfo { ImageSize = 0, FileName = null, ImageData = 0 };
    //}
    public string HomeTown { get; set; }
    public virtual UserProfileInfo UserProfileInfo { get; set; }

and this is my userProfileInfo class where i want to save every user's profile pic after they have completed the registration----

  public class UserProfileInfo
  { 
   // [Key, ForeignKey("ApplicationUser")]
    [Key]
    public int Id { get; set; }
    public int ImageSize { get; set; }
    public string FileName { get; set; }
    public byte[] ImageData { get; set; }

   [ForeignKey("Id")]
    public virtual ApplicationUser ApplicationUser { get; set; }
}

and this is my DbContext class -----

    public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

    public DbSet<UserProfileInfo> UserProfileInfo { get; set; }

Now, the problem is that i am unable to configure one to one relationship between ApplicationUser class and UserProfileInfo class.I have tried various ways to do it and followed some stack overflow questions previosly asked But after i had completed my registration form, it states error------

Unable to determine the principal end of an association between the types 'CodeFirstContext.ApplicationUser' and 'CodeFirstContext.UserProfileInfo'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

i have also tried to put relationship with the help of fluent api-----

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
       // base.OnModelCreating(modelBuilder);

        //// Configure Id as PK for UserProfileInfo class
        modelBuilder.Entity<UserProfileInfo>()
            .HasKey(e => e.Id);

        // Configure Id as FK for UserProfileInfo
        modelBuilder.Entity<ApplicationUser>()
            .HasOptional(s => s.UserProfileInfo)
            .WithRequired(ad => ad.ApplicationUser);
    }

This way i also failed.Please suggest me how to configure it.


回答1:


You are almost there. First, you can drop all annotations on your properties (Key, foreignkey), as ef by convention makes your column with name Id the primary key (and your relationships relate to this again).

Second, you only need to fluently map your relationship from one entity, for example from Applicationuser to UserProfileInfo like this:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ApplicationUser>()
            .HasOptional(c => c.UserProfileInfo)
            .WithRequired(d => d.ApplicationUser);
        base.OnModelCreating(modelBuilder);
    }

Note: this if your profile relationship is optional, otherwise use, HasRequired. If you now wanted to add profile settings for a user you could:

var user = UserManager.FindById(User.Identity.GetUserId());
var up = new UserProfileInfo {ImageSize = 12};
user.UserProfileInfo = up;
UserManager.Update(user);

More about ef fluent mappings here: https://msdn.microsoft.com/en-us/data/hh134698.aspx

EDIT: To Assign a UserProfileInfo to an ApplicationUser you could either:

1

// get user via UserManager
var user = UserManager.FindById(User.Identity.GetUserId());
// create new UserProfileInfo
var up = new UserProfileInfo {ImageSize = 12};
// assign UserProfileInfo to user, ef will figure out that this info goes into the corresponding UserProfileInfo table
user.UserProfileInfo = up;
// update via UserManager
UserManager.Update(user);

or 2.

// logged in user id
var userId = User.Identity.GetUserId();
using (var db = new ApplicationDbContext())
{
     // get user from context
     var user = db.Users.First(c => c.Id == userId);
     // new UserProfileInfo
     var up = new UserProfileInfo {ImageSize = 12};'
     // assign UserProfileInfo to user
     user.UserProfileInfo = up;
     // save changes
     db.SaveChanges();
 }

Lastly if you would like to update userprofileinfo instead of always creating a new one. you could do it like this:

// get existing or create new UserProfileInfo
var up = user.UserProfileInfo ?? new UserProfileInfo();
// update with new values 
up.ImageSize = 17;

Note that You dont need to care about the foreign key ApplicationUser_Id, EF figures this out itself when you assign UserProfileInfo to an ApplicationUser.

And: if you absolutely want to expose the foreign key for ApplicationUser in UserProfileInfo. you could add a property named ApplicationUserId in class UserProfileInfo. By convention Ef understands this. IF you require a different name for this foreign key you can extend your fluent mapping by using .HasForeignKey(fk=>fk.YourForeignKeyPropertyHere)



来源:https://stackoverflow.com/questions/33016771/configuring-one-to-one-relationship-in-asp-net-identity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!