我有一个这样的类:
public sealed class User
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Id { get; private set; }
[Required] public string GroupId { get; set; }
[Required] public bool IsAdmin { get; set; }
}
另一个:
public sealed class Group
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Id { get; private set; }
[ForeignKey("GroupId")]
public List<User> Users { get; set; }
}
User
类的IsAdmin
属性表示用户是否为管理员。我想做的是添加一个新属性到Group
:
public List<User> Admins { get; set; }
此新列表将包含属于其组管理员的所有用户,这意味着其属性IsAdmin
具有值true
。我已经考虑过为此属性使用自定义 getter,如下所示:
public List<User> Admins
{
get
{
return this.Users.Where(user => user.IsAdmin);
}
}
但是,我想知道实体框架是否可以为我解决这个问题。在我的脑海中,我可以想象它以类似于GroupId
用于Users
列表的方式使用IsAdmin
,其中每个具有User.GroupId = "foo"
的用户都包含在具有Group.Id = "foo"
的组的Users
列表中。
所以我的问题是,我如何告诉 EF 使用用户的IsAdmin
属性作为外键来填充Admins
?
因此,首先,在这种情况下使用术语"外键"是错误的。IsAdmin不是外键,充其量只是一个鉴别器。
其次,你可以像这样使用 [NotMapped] 属性
[NotMapped]
public List<User> Admins
{
get
{
return this.Users.Where(user => user.IsAdmin);
}
}
以便 EF 忽略该属性并且不尝试与其创建任何关系,这样,您将在访问管理员时获得所需的延迟加载值。
最后,我认为你的数据结构都是错误的。除非用户只能是一个组的成员,或者作为一个组中的管理员使他们成为他们所属的所有组的管理员,否则您的结构从域角度来看是有意义的,但从数据角度来看仍然是错误的。 我建议您做的是将管理员<->用户关系视为多对多,并引入一个相交对象 GroupAdmins,该对象将具有组的 ID 和用户的 ID。您可以让 EF 自动创建该相交表,为您提供更简单的域模型,也可以手动执行此操作,请参阅此处的前者文章。
重新阅读,您的问题,上述内容不适用,但是,如果遇到类似情况的人遇到此答案,我将将其留在这里。