问题领域
假设我有一个看起来像这样的实体......
public class HierarchyObject
{
[Key]
public int Id { get; set; }
[ForeignKey("Parent")]
public int ParentId { get; set; }
public virtual HierarchyObject Parent { get; set; }
public virtual ICollection<HierarchyObject> Children { get; set; }
}
好的,现在我正在使用 EF,所以我可以简单地做一些类似...
var ctx = new MyContext();
var getAll = ctx.HierarchyObjects.AsQueryable();
现在假设我向这些对象添加了权限,因此某些用户只能对这些对象的一部分执行基本的 CRUD 操作,我现在可能会做类似...
getAll = getAll().Where(o => o.Permissions.Any(p => p.Read && UserId == currentUserId));
这仅返回用户可以访问的项目。
现在我想在可查询的端点后面公开它,假设是 OData。
OData 将允许我编写这样的 URL ...
~/Api/HierarchyObject?$Expand=Children
...这样做之后我就破坏了我的安全,因为 EF 代理不知道我的权限规则,结果将是“我有权访问的所有对象及其子对象”,而真正的问题应该是“所有我可以访问的对象扩展到我可以访问的所有子项。
所以我的问题是
有没有办法告诉 EF 在抓取子属性时它还应该应用 where 子句......
o.Children = o.Children.Where(o => o.Permissions.Any(p => p.Read && UserId == currentUserId));
...并在任何时候“代理”其中一个对象时将该规则应用于我的所有层次结构对象?
更多详情
我发现了这个:
How can I dynamically customize a POCO proxy in EF 4?
一切都很好,ssays 我试图做的事情在 EF4 中是不可能的,但我使用的是 EF6,所以我认为微软/其他人可能已经找到了解决这个问题的方法,现在允许一种体面的拦截方式/以某种方式覆盖代理创建过程,也许使用 IDbSet 类型作为规则 Hook 的驱动程序,让您以某种方式为关系爬网定义一些代理规则,但我还没有找到任何东西!
最佳答案
事实证明我在这件事上走错了路。 我发现我可以使用 EF 过滤器按类型限制返回的实体,而不是通过代理对象来防止关系爬行。
在 Nuget 上有一堆扩展 EF 功能的包,本质上是在运行任何业务逻辑代码之前提供上下文敏感的“数据库切割”。
关于c# - EF 代理和复杂的数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41063888/