简体   繁体   English

Microsoft.AspNet.Identity.EntityFramework.IdentityUser 的外键?

[英]Foreign Key To Microsoft.AspNet.Identity.EntityFramework.IdentityUser?

I'm in VS 2013 and have just created an MVC application.我在 VS 2013 中,刚刚创建了一个 MVC 应用程序。

I'm creating an object I intend to have a foreign key to the AspNetUsers table in the resulting database.我正在创建一个对象,我打算在结果数据库中拥有一个指向 AspNetUsers 表的外键。 The project does have an ApplicationUser (deriving from IdentityUser) that looks like a property-column match with the AspNetUsers table.该项目确实有一个 ApplicationUser(源自 IdentityUser),它看起来像与 AspNetUsers 表匹配的属性列。

How do we properly declare a foreign key to this?我们如何正确地为此声明一个外键?

public MyObject
{
   public string UserId { get; set; }

   [ForeignKey("UserId")]
   public ApplicationUser User { get; set;}

   // other properties
}

Now, I modify ApplicationUser to have a collection of MyObjects:现在,我修改 ApplicationUser 以获得 MyObjects 的集合:

public ApplicationUser : IdentityUser
{
     public virtual ICollection<MyObject> MyObjects { get; set; }    
}

This seems to be how to do one-to-many in EF Code First.这似乎是EF Code First中如何进行一对多。 However, when I update-database, I'm getting the errors that say Identity members (IdentityUserLogin, IdentityUserRole, etc.) have no keys defined.但是,当我更新数据库时,我收到错误消息,指出身份成员(IdentityUserLogin、IdentityUserRole 等)没有定义密钥。 Perhaps those classes were not meant to participate in EF Code First Migrations?也许这些课程不打算参与 EF Code First 迁移?

I could go "to the back" and add the foreign key via SQL statements, but if I wanted to update again from Code First, I might get errors (that the database doesn't currently match the older migration or something like that).我可以“返回”并通过 SQL 语句添加外键,但是如果我想从 Code First 再次更新,我可能会收到错误(数据库当前与旧迁移不匹配或类似)。

How do we properly foreign-key reference those membership tables?我们如何正确使用外键引用这些成员资格表?

I also tried to create an AspNetUser class with matching properties of the AspNetUsers table.我还尝试使用 AspNetUsers 表的匹配属性创建一个 AspNetUser 类。 Instead of "public ApplicationUser" on the Client class, I declared "public AspNetUser".我在 Client 类上声明了“public AspNetUser”,而不是“public ApplicationUser”。 Doing this resulted in a migration failure - "Automatic migration was not applied because it would result in data loss."这样做会导致迁移失败 - “未应用自动迁移,因为它会导致数据丢失。”

So, what to do?那么,该怎么办?

It is easy to create a one-to-many relationship between ApplicationUser and MyObject and add a "UserId" foreign key in your MyObjects table.ApplicationUserMyObject之间创建一对多关系并在MyObjects表中添加“UserId”外键很容易。 What I like about this solution is that it follows EF conventions and there is no need for [ForeignKey] attribute in your model:我喜欢这个解决方案的地方在于它遵循 EF 约定,并且您的模型中不需要[ForeignKey]属性:

public class ApplicationUser : IdentityUser
{
    public virtual ICollection<MyObject> MyObjects { get; set; }
}

public class MyObject
{
    public int MyObjectId { get; set; }

    public string MyObjectName { get; set; }

    // other properties

    public virtual ApplicationUser ApplicationUser { get; set; }
}

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

    public DbSet<MyObject> MyObjects { get; set; }

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

        modelBuilder.Entity<MyObject>()
            .HasRequired(c => c.ApplicationUser)
            .WithMany(t => t.MyObjects)
            .Map(m => m.MapKey("UserId"));
    }
}

Notice the use of Fluent API to create a "UserId" foreign key in your MyObjects table.请注意使用 Fluent API 在MyObjects表中创建“UserId”外键。 This solution would still work without adding the Fluent API, but then your foreign key column would be named "ApplicationUser_Id" in your MyObjects table by convention.此解决方案在不添加 Fluent API 的情况下仍然可以工作,但是按照惯例,您的外键列将在MyObjects表中命名为“ApplicationUser_Id”。

I would do the following: In the ApplicationUser class, add a ForeignKey attribute,我将执行以下操作:在ApplicationUser类中,添加一个ForeignKey属性,

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

and in your model where you want to track to which user it belongs,在您想要跟踪它属于哪个用户的模型中,

public MyObject {
    public string UserId { get; set; }

    // other properties
}

You don't need to store the whole ApplicationUser instance in the MyObject class, and the UserID will be generated automatically.您不需要将整个ApplicationUser实例存储在MyObject类中, UserID将自动生成。 It is important that is is of type string , as is the ID of the ApplicationUser !重要的是它是string类型, ApplicationUserID也是如此!

public MyObject
{
   .. other properties

   [MaxLength(128), ForeignKey("ApplicationUser")]
   public virtual string UserId { get; set; }

   public virtual ApplicationUser ApplicationUser { get; set;}
}

The ASP.NET Identity classes doesn't use attributes to define the relations, they expect the relations to be configured by the DbContext. ASP.NET Identity 类不使用属性来定义关系,它们希望由 DbContext 配置关系。

The default DbContext used with ASP.NET Identity, IdentityDbContext<TUser> includes the configuration.与 ASP.NET Identity 一起使用的默认 DbContext IdentityDbContext<TUser>包括配置。 So if you make your DbContext class inherit from IdentityDbContext<ApplicationUser> you should be all set.所以如果你让你的 DbContext 类继承自IdentityDbContext<ApplicationUser>你应该一切都准备好了。

Update更新

If you still get error: "Automatic migration was not applied because it would result in data loss."如果仍然出现错误:“未应用自动迁移,因为它会导致数据丢失。” then do:然后做:

get Update-Database -Force

If you still get error messages about IdentityUserLogin, IdentityUserRole, etc. have no keys defined then you most likely are overriding the OnModelCreating method in your DbContext without calling the base method first.如果您仍然收到有关 IdentityUserLogin、IdentityUserRole 等未定义键的错误消息,那么您很可能在未先调用基本方法的情况下覆盖了OnModelCreating中的 OnModelCreating 方法。 Add a call to the base like this:像这样添加对基的调用:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelbuilder);
    // your code here
}

End of Update更新结束

If you don't want to inherit from IdentityDbContext you need to add some configuration for the Identity classes.如果您不想从IdentityDbContext继承,则需要为 Identity 类添加一些配置。 One way to do this is by overriding OnModelCreating .一种方法是覆盖OnModelCreating This is where IdentityDbContext<ApplicationUser> configure the entity framework mappings.这是IdentityDbContext<ApplicationUser>配置实体框架映射的地方。 If you add this to your DbContext class it should set up the mappings you need.如果您将此添加到您的 DbContext 类,它应该设置您需要的映射。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
    modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id);
    modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
}

I think you have it backwards.我认为你有它倒退。 Maybe try something like:也许尝试这样的事情:

public MyCustomUser : IUser
{
   public string Id { get; set; }

   public string FavoriteHairColor { get; set;}
}

public ApplicationUser : IdentityUser
{
     public virtual ICollection<MyCustomUser> MyCustomUsers{ get; set; }    
}

I'm going from memory here so I might be a little off.我从这里开始记忆,所以我可能有点不对劲。 Anyway, the important things is to have your EF user class inherit from IUser.无论如何,重要的是让您的 EF 用户类继承自 IUser。

this is also an alternative way for @kimbaudi suggestion.这也是@kimbaudi 建议的另一种方式。 With this, you don't need to define mapping key attribute instead you can use your own defined Model attribute.有了这个,您不需要定义映射键属性,而是可以使用自己定义的模型属性。

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


   public ApplicationUser User { get; set; }

    // other properties
}

public class ApplicationUser : IdentityUser
{ 
    public virtual ICollection<MyObject> MyObjects { get; set; }      

}

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

    public DbSet<MyObject> MyObjects { get; set; }

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

        modelBuilder.Entity<MyObject>()
        .HasRequired(po => po.User)
        .WithMany(a => a.MyObjects)
        .HasForeignKey(po => po.UserId);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 &#39;Microsoft.AspNet.Identity.EntityFramework.IdentityUser&#39;未标记为可序列化 - 'Microsoft.AspNet.Identity.EntityFramework.IdentityUser' is not marked as serializable 没有从 ApplicationUser 到 Microsoft.AspNet.Identity.EntityFramework.IdentityUser 的隐式引用转换 - There is no implicit reference conversion from ApplicationUser to Microsoft.AspNet.Identity.EntityFramework.IdentityUser 为什么IdentityUser类在Microsoft.AspNet.Identity.EntityFramework命名空间中而不在Core包中? - Why is the IdentityUser class in the Microsoft.AspNet.Identity.EntityFramework namespace and not in the Core package? 实体类型 &#39;Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin<string> &#39; 需要定义一个键 - The entity type 'Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin<string>' requires a key to be defined .NET Standard 2.0中的Microsoft.AspNet.Identity和Microsoft.AspNet.Identity.EntityFramework - Microsoft.AspNet.Identity and Microsoft.AspNet.Identity.EntityFramework in .NET Standard 2.0 自定义Microsoft.AspNet.Identity.EntityFramework.UserStore <TUser> - custom Microsoft.AspNet.Identity.EntityFramework.UserStore<TUser> 无法从“字符串”转换为“ Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole - cannot convert from 'string' to 'Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole vsts构建在Microsoft.AspNet.Identity.EntityFramework上失败 - vsts build fails on Microsoft.AspNet.Identity.EntityFramework Nuget错误:“ EntityFramework 5.0.0”与“ Microsoft.AspNet.Identity.EntityFramework 1.0.0不兼容” - Nuget error: 'EntityFramework 5.0.0' is not compatible with 'Microsoft.AspNet.Identity.EntityFramework 1.0.0 来自 api 的实体框架身份注册,具有自定义身份用户 - Entityframework identity register from api with custom identityUser
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM