0

I'm using code first to create a foreign key on YogaSpace that links the ApplicationUsers id to ApplicationUserRefId in the YogaSpace class. So every time I create and insert a new YogaSpace it fills the ApplicationUser id with the id of the person logged in. And I want it to be a one-to-many where the YogaSpace object can be many for one ApplicationUser id. But I'm getting key errors.

public class YogaSpace
{
    // for a one-to-one relationship
    // great tutorial on code-first
    //http://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

    [Index (IsUnique = true)]
    [Key]
    [Column(Order = 1)]
    public int YogaSpaceId { get; set; }

    [Key]
    [Column(Order = 2)]
    public int ApplicationUserRefId { get; set; }

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

    [Required]
    public string Name { get; set; }

}

Here is my ApplicationUser class

public class ApplicationUser : IdentityUser
{   
    //other members left out to save space
    public virtual ICollection<YogaSpace> YogaSpaces { 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;
    }
}

Here are all the errors. When updating the database, it's throwing related to keys.

One or more validation errors were detected during model generation:

GiftExchange.DataLayer.Models.IdentityUserLogin: : EntityType 'IdentityUserLogin' >has no key defined. Define the key for this EntityType. GiftExchange.DataLayer.Models.IdentityUserRole: : EntityType 'IdentityUserRole' >has no key defined. Define the key for this EntityType.

UPDATE! I tried overriding the class that its asking me to create a key for but it still doesn't work

public class TestIdentityUserLogin : IdentityUserLogin
{
    [Key]
    public override string UserId { get; set; }
}

I tried adding the keys using fluent api found in this link [User in Entity type MVC5 EF6

In my YogaSpaceContext I included

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
        modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
    }

and it seemed to remove the no key defined errors from the package manager for updating the database. But how would I implement it in code first?

Community
  • 1
  • 1
chuckd
  • 13,460
  • 29
  • 152
  • 331
  • The fluent API *is* code first. You can't apply attributes to base classes through derived classes, so the fluent API is all you've got. – Gert Arnold Jan 29 '15 at 22:20
  • Why not modelbuild for the ApplicationUser . `modelBuilder.Entity().HasKey(_ => _.Id);` I was having similar problems and that worked. However i am not sure why it worked, which is bothering me –  Mar 27 '15 at 13:35

2 Answers2

0

I would do the following: In the ApplicationUser class, add a ForeignKey attribute,

public ApplicationUser : IdentityUser {
    [ForeignKey("UserID")]
    public virtual ICollection<YogaSpace> YogaSpaces { get; set; } 

    // other properties
}

and in the YogaSpace model where you want to track to which ApplicationUser it belongs,

public class YogaSpace{
    public string UserId { get; set; }

    // other properties
}

You don't need to store the whole ApplicationUser instance in the YogaSpace class, and the UserID will be generated automatically. It is important that is is of type string, as is the ID of the ApplicationUser!

(Duplicated my answer to Foreign Key To Microsoft.AspNet.Identity.EntityFramework.IdentityUser?)

Community
  • 1
  • 1
EluciusFTW
  • 2,565
  • 6
  • 42
  • 59
-2

Actually I think you should try something different if you're using code-first, for example..

Your ApplicationUser class:

class ApplicationUser
{
     public int Id { get; set; }
     public ICollection<YogaSpace> YogaSpaces { get; set; }
}

You have a collection of YogaSpaces, and then, your YogaSpace class like:

public class YogaSpace
{
   public int Id { get; set; };
   public int AnotherProperty { get; set; }
}

And EF will create the right tables for you.

PS: Not tested, but that's the way.

Will
  • 1
  • What I want to do is simple. When I create a new YogaSpace I want it to have a OwnerId that belongs to the person logged in. Then when I search for YogaSpaces I can fetch all YogaSpaces that belong to that person. Ex. I have an Id in applicationuser of 23 and I want to search for all YogaSpaces with a property value ('someId') of 23. So everytime I create a new YogaSpace it inserts the id from applicationuser into the table. I can do it manually but it seems like code first or identity 2 would have something that supports that????? – chuckd Jan 29 '15 at 06:45
  • `Id` property is coming from inherited object `IdentityUser`. – trailmax Jan 29 '15 at 11:31