Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在ASP.NET核心标识中将多个模型有条件地映射到一个表(AspNetUsers)?_C#_Asp.net Core_Entity Framework Core_Asp.net Core Mvc_Asp.net Identity - Fatal编程技术网

C# 如何在ASP.NET核心标识中将多个模型有条件地映射到一个表(AspNetUsers)?

C# 如何在ASP.NET核心标识中将多个模型有条件地映射到一个表(AspNetUsers)?,c#,asp.net-core,entity-framework-core,asp.net-core-mvc,asp.net-identity,C#,Asp.net Core,Entity Framework Core,Asp.net Core Mvc,Asp.net Identity,我正在ASP.NET核心MVC中创建一个学习评估web应用程序。 我计划有两个独立的数据库:一个用于使用Identity Framework的用户,另一个用于使用Dapper的我的数据。但是,我有一些模型与我的UsersStructor,Student有关系。下面是我绘制的实体关系图,显示了这些关系: 例如,我必须为每个学生实例包含一个课程导航属性。同样,TestInstance包含讲师和学生的导航属性,明确区分了两个用户类。 我还需要另一个名为Administrator的用户类: 用户类 责

我正在ASP.NET核心MVC中创建一个学习评估web应用程序。 我计划有两个独立的数据库:一个用于使用Identity Framework的用户,另一个用于使用Dapper的我的数据。但是,我有一些模型与我的UsersStructor,Student有关系。下面是我绘制的实体关系图,显示了这些关系:

例如,我必须为每个学生实例包含一个课程导航属性。同样,TestInstance包含讲师和学生的导航属性,明确区分了两个用户类。 我还需要另一个名为Administrator的用户类:

用户类 责任 大学生 参加考试 教练 创建和安排测试 管理员 管理教师和学生帐户和课程。拥有讲师的所有特权
您可以将TPT与EF Core 5配合使用 例如,此项目将TPT与ASP.NET核心标识集成在一起

结果是:

您可以将TPT与EF Core 5配合使用 例如,此项目将TPT与ASP.NET核心标识集成在一起

结果是:
讲师也可以是管理员吗?如何处理此类多角色授权

也许这与本例无关,但我喜欢在遇到用户因新见解而提出的更改请求之前考虑这些质量/架构问题

P>个人,我会考虑创建一个角色表,包含三个角色。使用单独的UserRole表,可以在用户及其角色之间创建多对多关系。因此,我将在这里使用一种组合,而不是使用继承/派生

我认为您当前使用AspNetUsers的逻辑将保持不变。也许您可以使用Identity添加策略来实现基于这两个额外的角色相关表的访问控制

编辑

您还可以更进一步,创建一个额外的Right表,其中包含单独的用户权限,如参加测试、创建测试、安排测试、管理帐户等。您可以创建一个单独的RolerRight表,将这些权限分配给所需的角色

这将使您的角色更加动态,甚至可以由用户配置。当然,在后一种情况下,只有用户有权创建和管理角色

在代码中,您可以检查用户是否拥有由其角色分配的特定权限。例如,在负责创建测试的代码中,您可能实际上希望检查用户是否有权创建测试,而不是显式检查用户是否是讲师


无论如何,这只是我对这个问题的50美分。希望有帮助。

讲师也可以是管理员吗?如何处理此类多角色授权

也许这与本例无关,但我喜欢在遇到用户因新见解而提出的更改请求之前考虑这些质量/架构问题

P>个人,我会考虑创建一个角色表,包含三个角色。使用单独的UserRole表,可以在用户及其角色之间创建多对多关系。因此,我将在这里使用一种组合,而不是使用继承/派生

我认为您当前使用AspNetUsers的逻辑将保持不变。也许您可以使用Identity添加策略来实现基于这两个额外的角色相关表的访问控制

编辑

您还可以更进一步,创建一个额外的Right表,其中包含单独的用户权限,如参加测试、创建测试、安排测试、管理帐户等。您可以创建一个单独的RolerRight表,将这些权限分配给所需的角色

这将使您的角色更加动态,甚至可以由用户配置。当然,在后一种情况下,只有用户有权创建和管理角色

在代码中,您可以检查用户是否拥有由其角色分配的特定权限。例如,在负责创建测试的代码中,您可能实际上希望检查用户是否有权创建测试,而不是显式检查用户是否是讲师


无论如何,这只是我对这个问题的50美分。希望有帮助。

我认为您可以通过创建一个users表来轻松解决此问题,该表是可能访问系统的所有系统用户的清单,包括学生、讲师、管理员,其中包含共享属性,如ID、名称、电子邮件地址等。请确保存储所有密码

然后,您有两个前进的选项:您可以使用这里的多表方法,只需让每个“角色表”通过userId连接到users表,并存储该角色的唯一属性:在您的示例中 例如,学生表可能只是一个课程Id和一个用户Id。这允许您在发现每个角色时使用附加属性自定义它们

或者,您可以将角色合并到一个表中,但是除非您做一些工作来抽象唯一的属性,否则您可能会得到一个非常宽的表,其中包含许多不适用于每个角色的属性的空白值。不要这样做。一开始很容易,但随着你的应用程序的增长,这张桌子会变成一团乱麻

只需添加一个“users”表,您就可以在对现有模式进行最小更改的情况下继续前进


另一个注意事项是:学生和课程之间的关系是1:1。我可能错了,但你可能希望这是一对多,因为大多数学生一次会选修多门课程。您的里程数可能会有所不同。

我认为,您可以通过创建一个用户表来非常轻松地解决此问题。该表是可能访问系统的所有系统用户的清单,包括学生、讲师、管理员,其中包含共享属性,如ID、姓名、电子邮件地址等。请确保存储所有密码

然后您有两个前进的选项:您可以使用这里的多表方法,只需让每个“角色表”通过userId连接到users表,并存储该角色的唯一属性:在您的示例中,学生表可能只是一个课程Id和一个用户Id。这允许您在发现每个角色时使用附加属性对其进行自定义

或者,您可以将角色合并到一个表中,但是除非您做一些工作来抽象唯一的属性,否则您可能会得到一个非常宽的表,其中包含许多不适用于每个角色的属性的空白值。不要这样做。一开始很容易,但随着你的应用程序的增长,这张桌子会变成一团乱麻

只需添加一个“users”表,您就可以在对现有模式进行最小更改的情况下继续前进

另一个注意事项是:学生和课程之间的关系是1:1。我可能错了,但你可能希望这是一对多,因为大多数学生一次会选修多门课程。您的里程可能会有所不同

因为紧密的整合

我想提出的是,存在紧密的一体化是核心问题。如果您的设计没有创建紧密集成,那么问题就会消失。您可以确定设计的集成度

关注点分离

对于为标识和应用程序本身维护一个单独的数据库,有很好的论据和实际用例。我最近开发并部署了这样一个应用程序,我对结果非常满意

第一个原因是当另一个应用程序添加到混合时会发生什么?。在野外,身份服务往往是孤立的:Azure AD、Google Cloud identity、AWS identity和Access Management等。除了固有的安全优势外,身份服务将支持您当前和未来的所有应用程序,并且不应在一个特定应用程序中紧密耦合

您的应用程序是基于web的:当用户需要移动应用程序时会发生什么?如果身份只能通过web应用程序访问,那么现在该怎么办?web应用程序可能使用基于会话的身份验证,因此您需要重写所有这些内容以支持移动应用程序。不会很漂亮的

另一方面,假设您已将服务分离。此外,由于您的设计要求标识服务与平台无关,因此实现了JWT JSON Web令牌对身份验证的支持。在这种情况下,移动应用程序的身份验证将完全相同,没有任何更改

让我们进一步了解这个场景:应用程序的用户已经厌倦了点击刷新来查看他们的测试分数是否可用。他们要求在考试成绩准备就绪时得到通知

移动推送通知的实现与应用程序的核心功能无关;它是一种以用户/平台为中心的功能。如果你不相信这是真的,考虑2FA双因素认证,利用移动设备作为第二个因素。 身份从来都不是一个好的实验场所,可以说是你最不想犯错误的地方。我相信你在身份解决方案中添加或修改的所有东西都有可能增加攻击向量。这是经典的吻的例子,保持简单,愚蠢

将用户连接到标识 用户表是指学生表和教师表;标识表引用了AspNetUsers

正如您所说的,如果表位于单个数据库中,它们将使用我们都知道和喜欢的标准开箱即用外键引用进行连接

有趣的是:我们可以自己动手了!从根本上说,外键是非常基本的概念 t:这是一个id,用它来引用一些东西。这是实现外键引用的唯一要求

请记住:用户与身份不同。系统中通常包含用户的数据,这些用户永远不会登录到他们的系统。此外,网站管理员很可能不是教师或学生

对于标准用例,我的建议是首先创建用户实体,然后创建标识。然后用您刚刚创建的标识的id更新用户表中的可选列

您希望为每个标识添加一个角色或用户类型claim讲师、学生,以便知道将在哪些用户表中找到该用户

因为紧密的整合

我想提出的是,存在紧密的一体化是核心问题。如果您的设计没有创建紧密集成,那么问题就会消失。您可以确定设计的集成度

关注点分离

对于为标识和应用程序本身维护一个单独的数据库,有很好的论据和实际用例。我最近开发并部署了这样一个应用程序,我对结果非常满意

第一个原因是当另一个应用程序添加到混合时会发生什么?。在野外,身份服务往往是孤立的:Azure AD、Google Cloud identity、AWS identity和Access Management等。除了固有的安全优势外,身份服务将支持您当前和未来的所有应用程序,并且不应在一个特定应用程序中紧密耦合

您的应用程序是基于web的:当用户需要移动应用程序时会发生什么?如果身份只能通过web应用程序访问,那么现在该怎么办?web应用程序可能使用基于会话的身份验证,因此您需要重写所有这些内容以支持移动应用程序。不会很漂亮的

另一方面,假设您已将服务分离。此外,由于您的设计要求标识服务与平台无关,因此实现了JWT JSON Web令牌对身份验证的支持。在这种情况下,移动应用程序的身份验证将完全相同,没有任何更改

让我们进一步了解这个场景:应用程序的用户已经厌倦了点击刷新来查看他们的测试分数是否可用。他们要求在考试成绩准备就绪时得到通知

移动推送通知的实现与应用程序的核心功能无关;它是一种以用户/平台为中心的功能。如果你不相信这是真的,考虑2FA双因素认证,利用移动设备作为第二个因素。 身份从来都不是一个好的实验场所,可以说是你最不想犯错误的地方。我相信你在身份解决方案中添加或修改的所有东西都有可能增加攻击向量。这是经典的吻的例子,保持简单,愚蠢

将用户连接到标识 用户表是指学生表和教师表;标识表引用了AspNetUsers

正如您所说的,如果表位于单个数据库中,它们将使用我们都知道和喜欢的标准开箱即用外键引用进行连接

有趣的是:我们可以自己动手了!从根本上说,外键是一个非常基本的概念:这里有一个id,用它来引用一些东西。这是实现外键引用的唯一要求

请记住:用户与身份不同。系统中通常包含用户的数据,这些用户永远不会登录到他们的系统。此外,网站管理员很可能不是教师或学生

对于标准用例,我的建议是首先创建用户实体,然后创建标识。然后用您刚刚创建的标识的id更新用户表中的可选列


您希望为每个标识添加角色或用户类型声明讲师、学生,以便知道您将在哪些用户表中找到该用户。

学生、讲师和管理员是否可以作为AspNetUsers的扩展?然后,AspNetUsers可以有重复的列,如ID、Name、DOB和Email,Administrator可以有AspNetUserID和Administrator类的其余列。@BrunoSerrano是的,它们基本上是AspNetUsers的扩展。一个简单的表继承就可以完成这项工作。如果我能至少在应用程序中用三个单独的模型类来表示这些用户,那就太好了。然后我可以在我的ER图中很容易地在TestInstance之类的模型中包含导航属性,其中包含对两个用户类的引用。学生、讲师和管理员可以是AspNetUsers的扩展吗?然后,AspNetUsers可以有重复的列,如ID、Name、DOB和Email,Administrator可以有AspNetUserID和Administ的其余列
是的,它们基本上是AspNetUsers的扩展。一个简单的表继承就可以完成这项工作。如果我至少在应用程序中可以在三个单独的模型类中表示这些用户,那就太好了,这样我就可以轻松地在模型中包括导航属性,比如在我的ER图中包含对两个用户类的引用的TestInstance。谢谢!如果您能在这里简短地描述一下流程以及执行此操作的代码段,那就太好了。@amalk不客气了。好了。嗨,这很好。谢谢,谢谢!如果您能在这里简短地描述一下流程以及执行此操作的代码段,那就太好了。@amalk不客气了。好了。嗨,这很好。谢谢。Identity已经有了名为AspNetRoles和AspNetUserRoles的表,我可能打算用它们来进行访问控制。另外,我真的很喜欢正确的表apporach,这将增加很多灵活性。在我的例子中,管理员拥有讲师的所有权限以及管理讲师和学生帐户的权限。Identity已经有了名为AspNetRoles和AspNetUserRoles的表,我可能计划使用这些表进行访问控制。另外,我真的很喜欢正确的表apporach,这将增加很多灵活性。在我的例子中,管理员拥有讲师的所有特权以及管理讲师和学生帐户的特权。我认为我将采用多表方法,并将标识保留在一个AspNetUsers表中。Identity还生成AspNetRoles表和一个名为AspNetUserRoles的联接表,我计划使用它来分配角色。然而,问题是我无法真正理解如何将学生、管理员和讲师模型/表映射到用于存储用户的表标识:AspNetUsers。我认为我将采用多表方法,并将标识保留在一个AspNetUsers表中。Identity还生成AspNetRoles表和一个名为AspNetUserRoles的联接表,我计划使用它来分配角色。然而,问题是我无法真正理解如何将学生、管理员和讲师模型/表映射到用于存储用户的表标识:AspNetUsers。我同意你的看法。我想通过从我的核心领域模型中隔离身份来放松耦合。我想知道是否有一种方法可以告诉学生、讲师和管理员模型根据他们在AspNetRoles表中的角色使用AspNetUsers表中的ID,我认为这可以解决问题。管理员用户将创建和管理学生和讲师帐户。欢迎任何其他解决方案。我编辑了我的答案以解决您的问题。请看一看,我同意你的看法。我想通过从我的核心领域模型中隔离身份来放松耦合。我想知道是否有一种方法可以告诉学生、讲师和管理员模型根据他们在AspNetRoles表中的角色使用AspNetUsers表中的ID,我认为这可以解决问题。管理员用户将创建和管理学生和讲师帐户。欢迎任何其他解决方案。我编辑了我的答案以解决您的问题。请看一看。
 public class ApplicationUser : IdentityUser<Guid>
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string NationalCode { get; set; }
        public DateTime BirthDate { get; set; }
        public Gender Gender { get; set; }

    }

 public class Student : ApplicationUser
    {
        public string FatherName { get; set; }
        public string PlaceOfBirth { get; set; }
        public string Address { get; set; }
        public string HomePhoneNumber { get; set; }
    }

 public class Teacher : ApplicationUser
    {
        public string FieldOfStudy { get; set; }
        public AcademicDegree AcademicDegree{ get; set; }
        public int YearsOfExperience { get; set; }
    }


  public class SchoolMgmtContext : IdentityDbContext<ApplicationUser,ApplicationRole,Guid>
    {


        public SchoolMgmtContext(DbContextOptions<SchoolMgmtContext> dbContextOptions)
            :base(dbContextOptions)
        {

        }

        public DbSet<Teacher> Teachers { get; set; }
        public DbSet<Student> Students { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            builder.Entity<ApplicationUser>().ToTable("Users");
            builder.Entity<ApplicationRole>().ToTable("Roles");

            builder.Entity<Student>().ToTable("Students");
            builder.Entity<Teacher>().ToTable("Teachers");
         

        }
    }