我正在构建一个用于学习目的的Web应用程序,它将是一个多用户应用程序。每个用户都将拥有他们的数据。我不是100%肯定如何实现这一点。我应该让Model1包含一个int UserId {get; set;}属性来保存用户GUID,还是应该是IdentityUser类型?然后在我的控制器中,我是否始终考虑我的查询的当前登录用户ID?我应该能够从会话中获取userId吗?
答案 0 :(得分:2)
出于某种原因,人们似乎对用户对象感到害怕,但它与任何其他类型的关系没有什么不同。是的,如果某个特定实体由用户“拥有”,那么该用户实体应该有一个外键。
我假设您已经在使用ASP.NET身份,因为您提到了IdentityUser
,但您似乎对实体框架如何处理关系感到困惑。从技术上讲,以下两个属性中的任何一个对生成的表具有相同的净效果(例如,名为User_Id
的列:
public string User_Id { get; set; }
OR
public virtual ApplicationUser User { get; set; }
在第二行中,Entity Framework看到您正在关联另一个实体,因此它会自行创建一个隐式外键来跟踪该关系。它不是您实体的一部分,但无论如何都在数据库表中。这是因为实体框架显然不能将整个用户对象存储在数据库级别的单个列中,也不希望它存储。
那就是说,你应该用于关系的代码实际上应该是这样的:
[ForeignKey("User")]
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
这有两件事:
您获得了导航属性User
,允许您通过此实体直接访问用户对象,同时还通知实体框架,此处需要跟踪的实体之间存在关系。
您有一个显式的外键属性UserId
,允许您在需要时实际获取外键。如果您希望能够执行从选择列表中选择相关项目的操作,则通常需要这样做,因为选择列表只能发布类似int或字符串的基本类型。如果您没有此属性,则必须更难以实现此类方案。
从技术上讲,ForeignKey
属性并不是严格要求的,因为实体框架会按惯例选择UserId
是User
的外键。但是,我认为最好明确表达您期望发生的事情,并且在惯例可能不正确的情况下,使用ForeignKey
的习惯将确保事情仍然按预期工作。
最后,关于授权,是的,您将按用户过滤实体,以便每个用户只能看到他们应该看到的内容。例如:
var widgets = db.Widgets.Where(m => m.UserId == User.Identity.GetUserId());
或者,在您正在显示或允许用户编辑单个项目的情况下:
var widget = db.Widgets.SingleOrDefault(m => m.Id == widgetId && m.UserId == User.Identity.GetUserId());
if (widget == null)
{
return new HttpNotFoundResult();
}
有了这个,用户甚至无法看到应用程序中的其他“小部件”。如果它不是他们的,他们会得到一个404,就好像它不存在事件一样。
答案 1 :(得分:0)
尝试考虑所有场景。您认为共享登录的可能性是否存在?无需登录或多次登录即可访问的用户也可能导致问题。在大多数情况下,使用UserId是一个很好的解决方案,但请确保您知道谁在使用它以及如何使用它。