将关系添加到ASP.NET Identity(数据库优先)中的ApplicationUser类 [英] Add relationships to the ApplicationUser class in ASP.NET Identity (Database First)

查看:65
本文介绍了将关系添加到ASP.NET Identity(数据库优先)中的ApplicationUser类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在ASP.NET MVC应用程序中使用ASP.NET Identity(数据库优先).我按照说明

I'm using ASP.NET Identity (Database First) in my ASP.NET MVC application. I followed the instructions here, to set up the ASP.NET Identity with database first approach.

我的AspNetUsers表与Employee表有关系(Employee表具有UserId外键,AspNetUsers实体具有ICollection<Employee>属性).

My AspNetUsers table has a relationship with the Employee table (The Employee table has a UserId foreign key, and the AspNetUsers entity has an ICollection<Employee> property).

我想将ICollection<Employee>属性添加到ApplicationUser中,如下所示:

I would like to add the ICollection<Employee> property to the ApplicationUser, like below:

public class ApplicationUser : IdentityUser<int, CustomUserLogin, CustomUserRole, CustomUserClaim>
{
    public ICollection<Employee> Employees { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, int> 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;
    }
}

但是,当我这样做时,会收到以下错误消息:

But, when I do that, I get the following error message:

EntityType'AspNetUserLogins'没有定义键.定义密钥 此EntityType. AspNetUserLogins:EntityType:EntitySet "AspNetUserLogins"基于类型"AspNetUserLogins",该类型没有 键已定义.

EntityType 'AspNetUserLogins' has no key defined. Define the key for this EntityType. AspNetUserLogins: EntityType: EntitySet 'AspNetUserLogins' is based on type 'AspNetUserLogins' that has no keys defined.

为什么会收到此错误消息?我该如何解决?

Why am I getting this error message? How can I fix that?

推荐答案

即使我在没有键和关系的另一个数据库中创建表,也无法重现该问题.因此,我确定您的模型存在问题.不幸的是,您没有添加我可以比较的代码,因此我无法分辨出什么并直接回答问题.我唯一能做的就是展示对我有用的东西.但是,首先我要说一些话.

I cannot reproduce the issue, even when I create the tables in another database without keys and relations. So I'm sure that there is a problem with your model. Unfortunately you didn't add code which I can compare, so I can't tell what is different and answer the question directly. The only thing I can do is to show what works for me. However, first I have some remarks.

我认为您不应该关注这篇文章.由于没有理由将上下文添加到现有数据库中.

I think you shouldn't follow the article. As there is no reason to add the context to an existing database.

就像伊万·斯托夫(Ivan Stoev)提到的那样,您不应混合使用上下文.身份上下文旨在对用户进行身份验证.它存储凭据,用户角色和声明.声明旨在添加有关用户的身份信息.

Like Ivan Stoev mentioned you are not supposed to mix contexts. The Identity context is meant to authenticate the user. It stores the credentials, the roles of the user and claims. Where claims are meant to add identity information about the user.

实际上,可以删除ApplicationUser模板的默认Hometown字段,因为它是一个身份声明,应存储在AspNetUserClaims表中.不需要为ApplicationUser扩展它.实际上,我想不出任何理由来扩展ApplicationUser.

In fact, the default Hometown field of the ApplicationUser template can be removed, as it is an identity claim which should be stored in the AspNetUserClaims table. Not something you need to extend the ApplicationUser for. Actually I can't think of any reason to extend the ApplicationUser.

关于角色,这些并不是真正的要求,因为它们不提供任何有关身份的信息,而是用于授权.这就是将它们存储在AspNetUserRoles表中的原因.不幸的是,角色作为角色声明被添加到身份中,这使事情变得混乱.

About the roles, these are not really claims, as they tell nothing about the identity but rather are used for authorization. That's why it's fine that they are stored in the AspNetUserRoles table. Unfortunately roles are added to the identity as role claims, which makes things confusing.

请注意,身份信息存在于权利要求中.这意味着应用程序不必调用Identity上下文.例如. User.IsInRole检查当前身份的角色声明,而不是表中存储的角色.

Please note that the Identity information is present in the claims. This means that the application doesn't have to call the Identity context. E.g. User.IsInRole checks the role claims of the current identity, not the roles stored in the table.

关于不同的上下文,另一个上下文(我通常将其称为业务模型)与Identity上下文没有任何共同之处.电子邮件和其他字段不是组成部分,对业务模型也没有意义.您可能会认为这些字段是多余的,但实际上并非如此.我可以使用Google帐户登录,但是对于公司来说,请使用我的工作电子邮件地址.

About the different contexts, the other context (which I usually call the business model) has nothing in common with the Identity context. Email and other fields are not part, nor have meaning to the business model. You may think that those fields are redundant, but in fact they are not. I could login using a google account, but for the business use my work email address.

有几个原因可以使上下文分开.

There are several reasons to keep the context seperated.

  • 关注点分离.假设您将来希望与另一个交换认证框架.像实施IdentityServer一样,以防您想要支持单点登录(SSO).
  • 如果另一个应用程序需要相同的登录名,则不能将users表移动到另一个数据库.因此,您最终还将向数据库中添加其他上下文.
  • 迁移时遇到问题.如果您混合使用上下文,则迁移将失败.
  • 这将使事情变得更加轻松.这是您遇到的第一个问题,而不是最后一个.

如文章中所述:

此时,如果您需要添加任何关系(例如外键) 从您自己的表到这些表,欢迎您这样做,但是 不要直接或稍后修改任何Entity Framework 2.0表 他们的任何POCO课程.这样做会导致基于以下原因的错误: 我收到的反馈.

At this point if you need to add any relationships (E.g. foreign keys) from your own tables to these tables you are welcome to do so but do not modify any of the Entity Framework 2.0 tables directly or later on any of their POCO classes. Doing so will result in errors based upon feedback I’ve received.

如果您不应该从应用程序访问身份上下文,那么如何管理信息?

So how to manage the information if you shouldn't access the identity context from your application?

对于当前用户,您不需要访问users表.所有信息都存在于身份声明中.访问身份上下文的唯一原因是允许用户登录.除了用户管理.

For the current user you don't need to access the users table. All the information is present in the identity claims. The only reason to access the identity context is to allow a user to login. Besides user management.

您可以通过添加对用户(用户ID)的引用来满足要求.如果您需要在报表中显示其他用户的信息(例如姓名),则在您的业务上下文中创建一个用户表来存储信息.您可以在此表中添加关系,因为它是同一上下文的一部分.

You can suffice by adding a reference to the user (the userid). If you need to show information of other users (like name) in a report, then create a user table in your business context to store the information. You can add relations to this table, as it is part of the same context.

如果您对此方法有疑问,请告诉我.

Please let me know if you have questions about this approach.

现在适合我的代码.像其他人提到的那样,不太可能添加以下行:

Now the code that works for me. Like others have mentioned, it is not likely that adding the line:

public ICollection<Employee> Employees { get; set; }

是原因.如果没有virtual关键字,我认为它甚至会被忽略(仍然为null).

is the cause. Without the virtual keyword I think it is even ignored (remains null).

当我按照本文的步骤进行操作时,我将得到以下模型:

When I follow the steps of the article then I end up with the following model:

public class ApplicationUser : IdentityUser
{
    public string Hometown { get; set; }

    //public virtual ICollection<Employee> Employees { 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;
    }
}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
        // Disable migrations
        //Database.SetInitializer<ApplicationDbContext>(null);
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }
}

然后添加Employee类并取消注释上面ApplicationUser类中的行:

And then I add the Employee class and uncomment the line in the ApplicationUser class above:

public class Employee
{
    public int Id { get; set; }

    public string Name { get; set; }

    //public virtual ApplicationUser ApplicationUser { get; set; }

    public string ApplicationUserId { get; set; }
}

在数据库中,我添加了表:

In the database I added the table:

CREATE TABLE [dbo].[Employees](
    [Id] [int] NOT NULL,
    [Name] [varchar](50) NOT NULL,
    [ApplicationUserId] [nvarchar](128) NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

您可以使用[ForeignKey]属性使用其他字段名称.

You can use the [ForeignKey] attribute to use a different field name.

您可以尝试这样做,也可以选择将两个上下文分开.

You can try this or choose to keep both contexts seperated instead.

这篇关于将关系添加到ASP.NET Identity(数据库优先)中的ApplicationUser类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆