【问题标题】:Integrating & Extending .NET Identity Classes in EF (Code first)在 EF 中集成和扩展 .NET 标识类(代码优先)
【发布时间】:2016-04-22 21:20:41
【问题描述】:

我正在开始一个全新的 .NET MVC 项目,对 EF 6 和 .NET 4.5 使用代码优先。我还想使用 Identity 框架,并在我的项目的上下文配置中扩展 Identity 基类。 (不确定我说的是否正确……我是一位经验丰富的 C#/.NET 开发人员,对 MVC、EF 和 Identity 有点陌生。)

我的问题:出了点问题。在尝试生成新迁移时,我遇到了错误:

POST.Data.Models.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
POST.Data.Models.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.

好的,所以,我的项目中有两个上下文,一个用于身份类,另一个用于其他所有内容。相同的数据库,并且任何一个上下文中的任何内容都没有引用另一个上下文中的任何内容。我这样定义实体:

public class ApplicationUser : IdentityUser { }
public class ApplicationRole : IdentityRole { }
public class ApplicationUserRole : IdentityUserRole { }
public class ApplicationUserClaim : IdentityUserClaim { }
public class ApplicationUserLogin : IdentityUserLogin { }

然后,我有一个这样的上下文类:

public partial class IdentityContext : IdentityDbContext
{
    public IdentityContext() : base() { }

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

    public DbSet<ApplicationUser> ApplicationUsers { get; set; }
    public DbSet<ApplicationUserClaim> ApplicationUserClaims { get; set; }
    public DbSet<ApplicationUserLogin> ApplicationUserLogins { get; set; }
    public DbSet<ApplicationRole> ApplicationRoles { get; set; }
    public DbSet<ApplicationUserRole> ApplicationUserRoles { get; set; }
}

不确定它是否重要,但我的配置看起来像这样:

internal sealed class Configuration : DbMigrationsConfiguration<POST.Data.Models.Context>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"ContextMigrations";
    }

    protected override void Seed(POST.Data.Models.Context context) {}
}

这会构建,但如果没有这些错误,我无法生成迁移,而且由于我对所有细节的知识和理解有限,我感到很困惑。

【问题讨论】:

    标签: c# asp.net-mvc entity-framework asp.net-mvc-4 asp.net-identity-3


    【解决方案1】:

    由于您没有为用户、角色等扩展任何身份实体,因此我不会费心创建您自己的身份子类(ApplicationUser、ApplicationRole 等)。您也不需要在上下文中定义任何与身份相关的 DbSet,因为它们是自动从 IdentityDbContext 继承的。但是,如果您想保留您的身份子类,您的 DbContext 应该从通用 IdentityDbContext 继承,因为这允许您定义您的自定义身份实体:

    public class IdentityContext : IdentityDbContext<ApplicationUser, ApplicationRole, string, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>
    {
       // Define other non-identity related dbsets
    }
    

    这将确保您的 DbContext 自动拥有所有相关的 DbSet 属性,而无需显式定义它们,因为它们是从通用 IdentityDbContext 类继承的。

    您也不需要在 OnModelCreating 中为任何身份内容定义任何迁移或流畅的 api 配置,因为您没有向身份实体添加任何内容(例如,其他 ApplicationUser 属性)。初始化 DbContext/EF 时将自动创建默认标识表。

    【讨论】:

    • 好的,这是我最初的方向,但创建了单独的子类,因为我想我将来想扩展它们,我现在也可以让我的生活更轻松。但老实说,我看到了不管它的逻辑。
    • 但是我的问题是,我希望我的措辞正确,是:如果我没有从 IdentityDbContext 继承的单独上下文,而是从 DbContext 继承,那么甚至根本就创建了基本身份类,这样这些具体实体又会在我的数据库中生成?我的意思是,在某些时候我需要说我希望创建 AspNet 身份表,对吗?又怎样?我有其他上下文,例如 MainContext:DbContext;那应该是 MainContext:IdentityDbContext 吗?
    • 好吧,没关系。我确实相信我已经弄清楚了... :-P 您只需创建单独的上下文并将其留空。
    • 除非您从 IdentityDbContext 类之一(通用或非通用)继承,否则不会生成它们。是的,一般方法是 MainContext 从 IdentityDbContext 继承,而不是拥有单独的上下文,以便可以一起查询/插入/更新等所有内容
    • 我将把它标记为答案,因为它确实解决了我的“问题”,并帮助我更好地理解我在做什么。但我还想指出,下面 Uilique 的回答也是有效的。
    【解决方案2】:

    您可以尝试使用属性Key 设置实体键。像这样的:

    using System.ComponentModel.DataAnnotations;
    
    namespace YourCompany.YourProject.Models
    {
        public class ApplicationUser : IdentityUser
        {
            [Key]
            public string UserId { get; set; }
        }
    
        public class ApplicationRole : IdentityRole
        {
            [Key]
            public string Id { get; set; }
        }
    
        public class ApplicationUserRole : IdentityUserRole
        {
            [Key]
            public string UserId { get; set; }
    
            [Key]
            public string RoleId { get; set; }
        }
    
        public class ApplicationUserClaim : IdentityUserClaim { }
    
        public class ApplicationUserLogin : IdentityUserLogin { }
    }
    

    希望对您有所帮助,如果有帮助,请将其标记为答案;)

    【讨论】:

    • 谢谢。我曾想过这一点,但没有尝试,因为我认为那些已经在基础类中标记为键......这让我更接近,因为我收到的最初错误已经消失了,是的。但是我现在收到关于隐藏的构建警告(我应该使用覆盖吗?)并且我的迁移仍然不会创建,原因是:“元数据集合中已经存在身份为'Id'的项目。参数名称:项目”
    猜你喜欢
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多