【问题标题】:Implementing service queryables: IQueryable to IEnumerable and back实现服务可查询:IQueryable 到 IEnumerable 并返回
【发布时间】:2014-01-16 18:56:49
【问题描述】:

在 RIA 服务(可能还有其他框架,如 WCF 数据服务)中,可以通过提供返回 IQuerably 的方法来实现数据服务方法。例如:

IQueryable<Customer> GetCustomers()
{
    return this.DbContext.Customers.Where(c => !c.IsDeleted);
}

然后,来自客户端的查询可以提供额外的过滤器(除其他外)。客户端提供的过滤器和只返回未删除客户的过滤器都将通过实体框架(或任何使用的 ORM)组合并发送到 SQL 中的数据库。

通常实体框架不足以表达一个想要编写的查询,在这种情况下,我们必须去 linq to objects:

IQueryable<CustomerWithFluff> GetCustomers()
{
    var customers =
        this.DbContext.Customers
        .Include("FluffBits")
        .Where(c => !c.IsDeleted)
        .ToList();

    return
        from c in customers
        select new CustomerWithFluff()
        {
            CustomerName = c.Name,
            ComplexFluff = String.Join(", ", from b in c.FluffBits select b.FluffText)
        };
}

到数据库的 sql 现在仍将包含对“IsDeleted”的限制,但不再包含客户端提供的任何进一步的过滤器:在获取所有数据后,这些过滤器将应用于 linq to objects 级别。

如果我不想让客户端过滤我需要与 linq-to-objects 组合的任何数据(本例中只有“ComplexFluff”),有没有办法仍然允许过滤简单投影的属性(本例中只有“CustomerName”)?

【问题讨论】:

  • 你最后一段,包含实际问题,不清楚。我建议改写它或举例说明你想做什么......

标签: linq wcf entity-framework linq-to-entities wcf-ria-services


【解决方案1】:

是的,但并不像人们想象的那么简单。您必须覆盖

public override IEnumerable Query(QueryDescription queryDescription, out IEnumerable<ValidationResult> validationErrors, out int totalCount)

方法,您可以在 queryDescription.Query 中获取将要针对您的 Queryable 执行的实际查询和表达式(即 queryDescription.Method.Invoke(this, queryDescription.ParamterValues) 返回的内容) .

然后您可以获取客户端发送的表达式并将其传递给您的方法(也许作为对 domainService 中某种字段的引用,不要忘记 WCF Ria 服务在每次调用时都会被实例化,即像常规 wcf perCall 实例模型),您必须在其中组合

var customers =
        this.DbContext.Customers
        .Include("FluffBits")
        .Where(c => !c.IsDeleted)

在“ToList()”方法调用之前。

不容易,但很有可能

【讨论】:

  • 好的,这让我更进一步。我仍然不知道如何结合这两个查询。我将 queryDescription 中的一个存储为服务类中的成员(我想一个有一个相当无用的 IQueryProvider)和带有实体框架查询提供程序的 IQueryable,这是我的查询。我现在想将前者的所有过滤器和排序顺序放入后者 - 但我该怎么做呢?
  • 没错。为此,您需要一个 Expression Visitor。几年前,我写了一篇小帖子,或多或少地证明了这一点,你仍然可以找到它here,虽然它是意大利语,但应该很容易翻译。如果您使用 linqpad,我也刚刚制作了一个脚本,您可以下载 here。另外,请记住,您需要一个相当复杂的重写器,因为您要将实体类型(CustomerWithFluff)中的表达式应用到另一个(客户)
  • 我在stackoverflow.com/questions/21207094/… 提交了一个新问题,以解决这个结合查询的特定问题。我认为无论我必须做什么,它可能已经在 RIA 服务库中实现了 - 毕竟,如果不是,为什么它们会将客户端查询表示为 DomainService.Query 中的 IQueryable 呢?并感谢您提供额外的指示,我会研究它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多