0

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.

duke
  • 1,816
  • 2
  • 18
  • 32

1 Answers1

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)

Indregaard
  • 1,195
  • 1
  • 18
  • 26
  • well thanks for ur reply.It has created a foreign key in database with name ApplicationUser_Id. Now, when i try to upload pic,it is not saving back in the database. I think problem is with FK created.Entity framework dont know what to put there. how to fix that bro.i have uploaded code here http://pastebin.com/ZWR2N4ZD – duke Oct 09 '15 at 08:38
  • by doing user = UserManager.FindById to find logged in user you could do as my answer above (set userprofileinfo an UserManager.Update). If you go via dbcontext like you have in your example you first have to fetch the user (var user = dc.Users.First(c => c.Id == someUserId);) then set the userprofile (user.UserProfileInfo = x). and lastly cs.SaveChanges. if you go the other way like you have done, set the user of UserProfile (IG.ApplicationUser = someuser). Note that your code only supports one upload pr user, you might want to change that to fetch user, check if info exists -> update or add – Indregaard Oct 09 '15 at 10:05
  • var user = UserManager.FindById(User.Identity.GetUserId()); var user1 = dc.Users.First(c => c.Id == user.Id); now, how to save that user1 in database FK column ApplicationUser_Id. I think problem is with foreign key is created on the fly in database and i am unable to get to that property via UserProfileInfo instance created above like IG.FileName or IG.ImageSize – duke Oct 09 '15 at 11:05
  • See my updated answer (no need to first fetch user from usermanager and then from dbcontext). – Indregaard Oct 09 '15 at 11:30
  • Bro Bro Bro magic happens finally got it saved. thank u. thanks for the guidance @Indregaard – duke Oct 09 '15 at 12:00