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



我有以下内容:-

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

现在我正在努力建立一个ERP系统。 在ERP系统中,我想添加以下内容:

  1. 名为"资产"的表,用于存储资产信息。
  2. ">
  3. 资产"表将有 2 列名为 "CreatedBy" + "ModifiedBy",它们应该存储创建和修改资产项的用户 ID。

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

  • 如果答案是肯定的,那么如果我们想升级我们的 ASPNET 标识版本,这种关系将来会中断吗?因为升级标识可能会导致创建新表或重命名现有表等,这可能会破坏资产表和 AspNetUsers 表之间的关系?

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

要执行的操作,最常见的方法是将其他模型作为 DbSet 添加到ApplicationDbContext中。

public class Asset
{
public string CreatedBy { get; set; }
public string UserId { get; set; }
public ApplicationUser User { get; set; }
}
public class ApplicationUser : IdentityUser
{
public IList<Asset> Assets { get; set; }
}
public class ApplicationDbCotext : IdentityDbContext<ApplicationUser>
{
public DbSet<Asset> Assets { get; set; }
}

正如我所提到的,这是最常见的方法,因为更新标识包应该不会对架构产生影响。也就是说,在推送到生产环境之前,应始终测试更新。

更新: 请注意,当您使用一对多关系时,您将在我们的资产模型中看到用户 ID 外键和用户对象的属性。由于这种关系,我们能够在用户中创建List<Asset>以完成一对多关系。这将允许我们直接查询属于用户的资产。

至于代码优先与数据库优先,区别实际上归结为如何定义实体框架和数据库之间的映射。

正如我在下面提到的,对于是否应将标识上下文与业务上下文分开,或者应将它们分离到单独的数据库中,没有一种适合所有答案的答案。现实情况是,只有您才能根据需要回答这个问题。将所有数据放在单个数据库中更为常见。也就是说,对于将有关用户的标识信息(例如其姓名,电子邮件和密码哈希)与其地址或付款信息等信息分开的安全性,有一些话要说。权衡是,您可能会发现自己试图维护应该绑定在一起但只是松散相关的对象,因为它们驻留在不同的数据库中。此外,您还需要确保使用不同的用户/密码连接到不同的数据库,并且最好将数据库放在不同的服务器上,因为如果服务器受到威胁,您将白白完成整个练习。获得理论安全性的权衡最终变得如此不切实际,因为您必须始终做另一件事,以至于您最终可以在一个数据库中看到所有内容,您可以在其中集中所有强化工作。

通常,当您使用单个身份验证File -> New项目时,应为您创建应用程序数据库上下文和应用程序用户对象。您可以根据需要向用户添加任意数量的属性和关系。

--更新 --

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

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

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

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

在这两种情况下,您都有用户。根据您的要求,这是一个逻辑 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);

业务不需要标识上下文。您所需要的只是 People.Id。仅当颁发令牌和创建/修改用户时,才使用标识上下文。

要获取 id,请使用如下内容:

var peopleId = int.Parse(Request.User.Identity.GetUserId());

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

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

在创建用户之前,您可以验证用户名和密码(使用用户管理器中的方法)并检查视图模型的模型状态。使用属性强制填充必填字段。

--原答案 --

为了不重复我自己,请在此处阅读我的答案。

简而言之,保持身份和业务分离。 以防万一从同一数据库中删除身份逻辑,例如在实现 IdentityServer 时。

您似乎在 AspNetUser 中有业务信息。如果是这样,请创建一个 Person 表并将信息移动到该表中。与模型中的该表相关。在表 Person 中,您可以添加对 AspNetUser 的引用。

--更新--

我想你理解正确,但我只会在这个答案中添加细节。

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

现在为什么要把这两者分开呢?业务模型和标识模型之间最重要的区别是标识表不能直接调用。我们使用 Owin 上下文来调用用户管理器/角色管理器。

这就是为什么我们不能将这些表添加到业务模型中的原因。事情可能会以不安全的方式进行更改。此外,我们不希望企业对授权有任何了解。如何完成此操作并不重要,只要标识和授权用户即可。

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

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

现在关于AspNetUser和People之间的联系。有四个选项:

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

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

  3. 将列 AspNetUserId 添加到人员。无需修改标识。您也可以将人员添加到身份模型,但我认为您无法在一个事务中创建两条记录。您可以使用User.Identity.GetId()来获取 AspNetUser.Id。但是,您可能会问自己,企业是否应该了解此信息。

  4. 将列 PeopleId 添加到 AspNetUsers。您需要扩展 IdentityUser 以添加 PeopleId。一个优点是你不需要 AspNetUser ID,但你可以使用人员的实际 ID。使用 OpenId 或声明时,您可以从声明中获取 People.Id,而不必向业务添加 AspNetUser.Id。(可选)可以将人员添加到模型,并作为扩展标识用户的导航属性。创建用户时,可以在一个事务中执行此操作。

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

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

哦,是的,有两种背景。标识模型,其中包含 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; }
}

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

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

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

有多种优点:

  1. 只有一个事务要添加用户。
  2. 您无法公开敏感字段,因为它们未在"人员"中映射。
  3. 您无法将人员添加到数据库,因为某些必填字段未在人员中映射。

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

相关内容

  • 没有找到相关文章

最新更新