我有一个如下课程:
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; }
}
IsAdmin
类的User
属性表示用户是否为管理员。我想要做的是向Group
添加新属性:
public List<User> Admins { get; set; }
此新列表将包含作为其群组管理员的所有用户,这意味着其属性IsAdmin
的值为true
。我考虑过为这个属性使用自定义getter,如下所示:
public List<User> Admins
{
get
{
return this.Users.Where(user => user.IsAdmin);
}
}
但是,我想知道Entity Framework是否可以为我处理这个问题。在我的脑海中,我可以想象它使用IsAdmin
的方式类似于GroupId
列表中使用Users
的方式,其中User.GroupId = "foo"
的每个用户都包含在Users
中{1}} Group.Id = "foo"
组的列表。
所以我的问题是,如何告诉EF使用用户的IsAdmin
属性作为填充Admins
的外键?
答案 0 :(得分:0)
首先,在这种情况下使用术语“外键”是错误的。 IsAdmin不是外键,充其量只是一个鉴别器。
其次,您可以使用[NotMapped]属性,如此
select *
from recipe_ingredients r1
where 1=1
and exists (select 1 from recipe_ingredients r2 where ingredient_id = 1 and r1.recipe_id = r2.recipe_id)
and exists (select 1 from recipe_ingredients r3 where ingredient_id = 2 and r1.recipe_id = r3.recipe_id) -- rinse and repeat these lines
这样EF就会忽略该属性,并且不会尝试与它建立任何关系,这样当您访问Admin时,您将获得所需的延迟值。
最后,我认为你的数据结构都错了。除非用户只能成为一个组的成员或者作为一个组中的管理员使他们成为他们所属的所有组的管理员,那么从域的角度来看,您的结构是有意义的,但从数据角度来看仍然是错误的。
我建议您查看Admin&lt; - &gt;用户关系为多对多,并引入交叉对象GroupAdmins,它将具有组的Id和用户的Id。您可以让EF自动创建的交叉表为您提供更简单的域模型,或者您可以手动执行,See article for the former here。
重新阅读,你的问题,以上内容不适用,但是,我会留在这里以防万一有类似情况的人在这个答案上发生。