加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

entity-framework – 导航属性过滤器

发布时间:2020-12-16 09:38:24 所属栏目:asp.Net 来源:网络整理
导读:我的问题是:如何为 navigation property实现默认的服务器端“过滤器”? 在我们的应用程序中,我们很少从数据库中删除任何内容.相反,我们实现“软删除”,其中每个表都有一个Deleted bit列.如果此列为true,则记录已被“删除”.如果它是假的,它没有. 这使我们
我的问题是:如何为 navigation property实现默认的服务器端“过滤器”?

在我们的应用程序中,我们很少从数据库中删除任何内容.相反,我们实现“软删除”,其中每个表都有一个Deleted bit列.如果此列为true,则记录已被“删除”.如果它是假的,它没有.

这使我们可以轻松“取消删除”客户端意外删除的记录.

默认情况下,我们当前的ASP.NET Web API仅返回“未删除”记录,除非从客户端将删除的参数发送为true.这个想法是服务的消费者不必担心指定他们只想要未删除的项目.

在Breeze中实现相同的功能非常简单,至少对于基本实体而言.例如,这里将是经典Todo示例的实现,添加一个“Deleted”位字段:

// Note: Will show only undeleted items by default unless you explicitly pass deleted = true.
    [HttpGet]
    public IQueryable<BreezeSampleTodoItem> Todos(bool deleted = false) {
        return _contextProvider.Context.Todos.Where(td => td.Deleted == deleted);
    }

在客户端,我们需要做的就是……

var query = breeze.EntityQuery.from("Todos");

…获得所有未删除的Todos,或者……

var query = breeze.EntityQuery.from("Todos").withParameters({deleted: true})

…获取所有删除的Todos.

但是,让我们说BreezeSampleTodoItem有一个子集合,用于完成Todo所需的工具.我们称之为“工具”.工具还实现了软删除.当我们执行使用展开来获取Todo及其工具的查询时,它将返回所有工具 – “已删除”或未删除.

但是,当Todo.Tools扩展时,如何默认过滤掉这些记录?

我发现对于可能需要扩展的每个项目都有单独的Web API方法,例如:

[HttpGet]
public IQueryable<Todo> TodoAndTools(bool deletedTodos = false,bool deletedTools = false)
{
    return // ...Code to get filtered Todos with filtered Tools
}

我在another SO post中找到了一些如何执行此操作的示例代码,但它需要手动编码Todo的每个属性.上述帖子中的代码也返回List,而不是IQueryable.此外,这需要为每个可能的扩展添加方法,这不是很酷.

基本上我正在寻找的是一些定义一条代码的方法,每当查询Todos时都会调用它,另一种方法是每次查询工具时 – 最好是能够传递一个定义它是否应该返回Deleted项的参数.这可以是服务器端堆栈中的任何位置 – 无论是Web API方法本身,还是Entity Framework的一部分(请注意,过滤包含扩展名为not supported in EF.)

解决方法

尽管我们已经讨论了允许过滤“扩展”的想法,但是Breeze无法完全按照您现在所要求的那样做,但我们真的需要更多关于社区是否会发现这些有用的反馈.请将此添加到breeze User Voice并投票.我们非常重视这些建议.

此外,正如您所指出的,EF不支持这一点.

但是……你能做的就是使用投影而不是扩展做一些非常相似的事情:

public IQueryable<Object> TodoAndTools(bool deleted = false,bool deletedTools = false) {
    var baseQuery = _contextProvider.Context.Todos.Where(td => td.Deleted == deleted);
    return baseQuery.Select(t => new {
      Todo: t,Tools: t.Tools.Where( tool => tool.Deleted = deletedTools);
    });
 }

这里有几点需要注意:

1)我们返回一个IQueryable of Object而不是Tou的IQueryable

2)Breeze将检查返回的有效负载并自动为返回的任何“entityTypes”创建breeze实体(即使在投影中).所以这个查询的结果将是一个javascript对象数组,每个对象都有两个属性; “待办事项”和“工具”,其中工具是“工具”实体的数组.好处是投影中返回的ToDo和Tool实体都将是“完整”的微风实体.

3)您仍然可以根据预计的属性名称传递客户端过滤器.即

var query = EntityQuery.from("TodoAndTools")
        .where("Todo.Description","startsWith","A")
        .using(em);

4)EF确实支持这一点.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读