EF 代理和复杂的数据结构

EF Proxies and complex data structures

问题领域

假设我有一个看起来像这样的实体......

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));

这 returns 只有用户可以访问的项目。

现在我想在可查询的端点后面公开它,比方说 OData。

OData 允许我像这样写 URL ...

~/Api/HierarchyObject?$Expand=Children

... 完成后我刚刚破坏了我的安全,因为 EF 代理不知道我的权限规则,结果将是 "All objects I have access to and their children",真正的问题应该是 "all objects I can access expand in to all their children that I have access to"。

所以我的问题是

有没有办法告诉 EF 在抓取子 属性 时还应该应用 where 子句...

o.Children = o.Children.Where(o => o.Permissions.Any(p => p.Read && UserId == currentUserId));

... 并在我所有的 Heirarchy 对象上随时应用该规则 "proxies" 其中之一?

更多详情

我发现了这个:

How can I dynamically customize a POCO proxy in EF 4?

一切都很好,ssays 我想做的事情在 EF4 中是不可能的,但我使用的是 EF6,所以我认为微软/其他人现在可能已经找到了解决这个问题的方法允许一个体面的方法以某种方式拦截/覆盖代理创建过程,也许使用 IDbSet 类型作为规则挂钩的驱动程序,让您以某种方式为关系爬网定义一些代理规则,但我还没有找到任何东西!

所以事实证明我在这件事上走错了路。 我发现我可以使用 EF 过滤器按类型限制返回的实体,而不是代理对象以防止关系爬行。

在 Nuget 上有一堆扩展 EF 功能的包,本质上是在 运行 其上的任何业务逻辑代码之前提供上下文敏感 "cut of the db"。