4

我的问题是:如何为导航属性实现默认的服务器端“过滤器” ?

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

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

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

在 Breeze 中实现同样的功能非常简单,至少对于基础实体来说是这样。例如,这将是经典 Todo 示例的实现,添加一个“已删除”位字段:

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

...获取所有未删除的待办事项,或者...

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

...获取所有已删除的待办事项。

但是,假设 BreezeSampleTodoItem 有一个子集合,用于完成该 Todo 所需的工具。我们将其称为“工具”。工具还实现了软删除。当我们执行一个expand用于获取 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
}

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

本质上,我正在寻找某种方法来定义一段代码,该代码在Todos被查询时被调用,而另一个被查询时被调用Tools- 最好能够传递一个定义它是否应该返回已删除项目的参数。这可能是服务器端堆栈上的任何位置 - 无论是在 Web API 方法中、本身还是实体框架的一部分(请注意,在 EF 中不支持过滤 Include 扩展。)

4

1 回答 1

1

虽然我们已经讨论了允许过滤“扩展”的想法,但 Breeze 目前无法完全满足您的要求,但我们确实需要更多反馈来了解社区是否会觉得这很有用。请将此添加到微风用户语音并投票。我们非常重视这些建议。

此外,正如您所指出的,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 的 Object 而不是 IQueryable 的 ToDo

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

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

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

4) EF确实支持这一点。

于 2013-01-30T21:44:01.870 回答