我可以在asp.net MVC-5项目中的aspnet数据库中添加新的自定义表

joh*_* Gu 7 asp.net asp.net-mvc asp.net-mvc-5 asp.net-identity asp.net-identity-2

我有以下内容: -

  1. Visual Studio 2013.
  2. 我创建了一个新的asp.net MVC-5 Web项目.
  3. 该项目使用的是asp.net identity 2.2.
  4. 对于身份验证方法,我选择了"个人用户帐户"
  5. 此过程创建了一个名为的新数据库 aspnet-OurProjectNanme-number
  6. 在自动生成的数据库中,我有一个名为AspNetUSers存储用户信息的表.

现在我正在建立一个ERP系统.在ERP系统内部,我想添加以下内容: -

  1. 一个名为"Asset"的表来存储资产信息.
  2. "资产"表将有2列名为" CreatedBy"+" ModifiedBy",它应存储创建和修改资产项的userId.

现在我不确定我需要如何实现这一目标?因为我需要在我的自定义表"Asset"和自动创建的"AspNetUsers"表之间添加一个外键.. 所以我可以在自动生成的数据库中添加我的自定义表"Asset",并在之间构建外键在Asset.CreatedByAspNetUsers.Id

  • 如果答案是肯定的,那么如果我们想要升级我们的aspnet身份版本,这种关系将来会破裂吗?因为升级身份可能会导致创建新表或重命名现有表等.这可能会破坏Asset表和AspNetUsers表之间的关系?

  • 如果答案是否(我不应该在自动生成的数据库中添加自定义表)那么我如何构建外键?在这种情况下我需要添加资产表?

小智 4

- 更新 -

答案越来越多,讨论也越来越。我想我已经展示了各种变化,这可能无助于理解它。所以这里是一个总结。如需解释,请阅读完整答案和讨论。

开箱即用,您有两个上下文:身份和业务。它们是分离的,因此您可以在不影响业务的情况下更改安全性。这样,升级安全性就不会破坏您的应用程序或其他模型。由于上下文是独立的,因此对其中一个的更改不会影响另一个。

旁注:您不打算直接访问 AspNet 身份表。实现 UserManager 并使用管理器的可用方法来执行操作。

现在说到逻辑,信息应该存储在哪里?作为一个简单的规则,只需问自己一个问题:它是安全的一部分还是业务的一部分?

在这两种情况下你都有用户。对于您的要求,这是逻辑上的 1:1 关系。但它们实际上是分开的。您可以在不提供登录名的情况下创建人员,也可以删除登录名,而无需删除用户(人员),例如由于历史原因。

您想要的只是查找当前用户的所有信息。所以您所需要的只是 People.Id。

无需更改 IdentityUser,您只需覆盖 AspNetUser.Id 即可创建 1:1 关系。

var appUser = new IdentityUser
{
    UserName = model.Email,
    Email = model.Email,
    Id = Convert.ToString(People.Id)
};
var identityResult = await userManager.CreateAsync(appUser, model.Password);
Run Code Online (Sandbox Code Playgroud)

您的业​​务不需要身份上下文。您所需要的只是 People.Id。身份上下文仅在颁发令牌和创建/修改用户时使用。

要获取 id,请使用类似以下内容:

 var peopleId = int.Parse(Request.User.Identity.GetUserId());
Run Code Online (Sandbox Code Playgroud)

现在您可以使用 Id 查询您的业务模型。

注册时,使用要存储的人员信息扩展 View 和 ViewModel。这将允许您同时添加 People 和 AspNetUser。尽管这不是一笔交易。但我认为,如果您首先执行检查,创建任何一个都不太可能失败。

您可以在创建用户之前验证用户名和密码(使用 UserManager 中的方法)并检查视图模型的 ModelState。使用属性强制填写必填字段。

——原答案——

为了不重复自己,请阅读我的答案

简而言之,将身份和业务分开。以防万一从同一个数据库中删除身份逻辑,就像实现 IdentityServer 时一样。

看来您在 AspNetUser 中有商业信息。如果是这样,请创建一个“人员”表并将信息移至该表。与模型中的该表相关。在表 Person 中,您可以添加对 AspNetUser 的引用。

- 更新 -

我认为您理解正确,但我只会在这个答案中添加详细信息。

在大多数情况下,所有表都在一个数据库中定义。但这并不意味着它们都是同一模型的一部分。可以有多个上下文。在这种情况下,一个用于身份,一个(或多个)用于业务。

现在为什么要把这两个分开呢?业务模型和身份模型之间最重要的区别是身份表不能直接调用。我们使用 Owin 上下文来调用 UserManager / RoleManager。

这就是为什么我们不能将这些表添加到业务模型中。事情可能会以不安全的方式改变。我们也不希望企业了解任何有关授权的知识。只要用户被识别并获得授权,如何完成并不重要。

此外,您可能希望实现 OpenId 和基于声明的授权。在这种情况下,信息不必在数据库中可用。

这个想法是创建身份表 AspNetUsers 和业务表 People 的 1:1 关系。可能存在一些冗余,例如电子邮件或(用户)名。但这不是问题。People 表应包含您想要在业务模型中使用的所有信息。并且业务表应该只与人员相关,而不是与 AspNetUsers 相关。

现在介绍 AspNetUsers 和 People 之间的链接。有四种选择:

  1. 设置 People.Id = AspNetUser.Id。请注意,AspNetUser.Id 不必是 GUID。您可以添加自己的值作为键。

  2. 设置 AspNetUser.Id = People.Id。

  3. 将列 AspNetUserId 添加到 People。无需对身份进行任何修改。您也可以将人员添加到身份模型中,但我认为您不能在一项事务中创建这两个记录。您可以使用 User.Identity.GetId() 来获取 AspNetUser.Id。然而,您可能会问自己,企业是否应该了解这些信息。

  4. 将列 PeopleId 添加到 AspNetUsers。您需要扩展 IdentityUser 以添加 PeopleId。一个优点是您不需要 AspNetUser Id,但您可以使用 People 的实际 Id。使用 OpenId 或声明时,您可以从声明中获取 People.Id,并且无需将 AspNetUser.Id 添加到业务中。您可以选择将 People 添加到模型中并作为扩展 IdentityUser 的导航属性。创建用户时,您可以在一次事务中完成此操作。

如果您在单独的上下文中创建用户,则需要自己处理回滚。但在向 People 添加记录之前,您已经可以测试是否可以添加 AspNetUser:具有有效的名称/电子邮件和密码。

由于您的业务模型与 People 表相关,因此您可以查询所有资产并连接 People 表以获取更多信息。或者您可以获取当前用户的所有资产。

o 是的,有两个上下文。身份模型,其中包含 AspNet...表 + 可选的人员。以及业务模型,其中包含所有 ERP 表 + 资产 + 人员。

您可以考虑对身份框架 2 使用代码优先,对业务模型使用数据库优先。

我希望这个对你有用。如果没有,我们继续聊天。

- 更新 -

答案集中在领域的分离:身份和业务。这就是为什么我没有讨论有关 AspNetUsers 表的一种可能的替代方案。

这两个模型是数据库的表示,这意味着数据库不必完全匹配。您可以随意映射表和字段,只要它们不破坏数据库逻辑即可。

由于 AspNetusers 和 People 具有 1:1 关系,两个表都存在于同一数据库中时,您也可以将两个表合并到 AspNetUsers 表中。您还可以向 AspNetUsers 表添加关系,但您可能希望添加额外的 Id (int) 列而不是使用当前的 Id(字符串)。

这并不意味着 People 类可以被丢弃,只是我们必须更改表映射:AspNetUsers。

例子:

[Table("AspNetUsers")]
public class People
{
    [Required]
    [StringLength(128)]
    public string Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,敏感字段未映射。然而我们需要 Id 字段。您现在可以读取和更新映射的字段。

您不必扩展 IdentityUser。您可以添加 AspNetUser,然后使用其他上下文中的 People 更新字段。但是,如果您想在单个事务中添加用户,扩展 IdentityUser 可能会更容易(确保您在 People 和 ApplicationUser 中定义新字段):

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

    public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

有多个优点:

  1. 添加用户只需一笔交易。
  2. 您无法公开敏感字段,因为它们未映射到人员中。
  3. 您无法将人员添加到数据库,因为某些必填字段未映射到人员中。

请注意,这可能不适用于所有类型的模型(代码优先/数据库优先+迁移)。

  • 您不需要创建新的数据库,所有表都可以存储在同一个数据库中。但两者有不同的背景。IdentityContext 和 BusinessContext。是的,如果出现问题,您需要自行回滚。但只要所有表都位于同一个数据库中,您就可以将 Person 添加到 IdentityModel 中,并使用 Person 扩展 IdentityUser(在模型中而不是数据库中创建关系),从而使其成为一个事务。 (2认同)