【问题标题】:Is Linq to WCF OData good for complex queriesLinq to WCF OData 是否适合复杂查询
【发布时间】:2014-01-06 01:15:57
【问题描述】:

目前,我们正在评估是否应该将 WCF 数据服务用作我们的应用程序的 DAL,并且我正在做一个 POC 以查看 WCF 数据服务是否适用于我们所有的场景。如果我有如下数据模型

并且我想获取 ID 为 1 的人订购的所有产品 > 100 美元,我将如何使用 Linq to OData 进行操作,因为在使用 OData 时对 Linq 运算符有很多限制。

dbContext.LineItems.Where(li => li.Order.PersonId == 1 && li.Product.Cost > 
120).Select( li => new { Product = li.Product})

上面的代码在 Sql 服务器上生成非常模糊的 T-SQL,理想情况下,我想从上到下钻取(如果使用 LINQ 查询或直接 T-SQL,则从订单到产品)连接表,但似乎总是使用 OData从下到上,我感觉不太舒服,并且在某些情况下,当我们必须在单个查询中查询两个以上的表时,会生成非常糟糕的 sql。

在我们的应用程序中,我们期待这样的场景,我们必须在单个查询中查询(写入条件)多达 4 个表并选择单个实体。对于这类复杂的查询,OData 是否正确?

感谢您阅读这么长的帖子。

【问题讨论】:

  • 通过 WCF 执行复杂查询是个坏主意,并且可能意味着您的域模型过于细化。如果您的模型不好,OData 是否可以执行复杂的查询是无关紧要的。您应该只公开实现场景所需的实体,而不是详细的数据库架构
  • @PanagiotisKanavos 我确信我们的数据库非常规范化(我假设这是正常的数据库设计),表之间的关系很复杂,我相信我们最终会遇到表 A 的主键和我们必须通过从表 A - 表 B - 表 C - 表 D 中获取表 D 中的数据,其中表之间的关系可以是 1-1、1-* 或 Many - many ,所以我正在争论是否 OData(WCF数据服务)在这种情况下是一个不错的选择,因为我们的架构师建议将 WCF 数据服务作为数据访问层(访问数据库的唯一方法,不能直接使用 EF)。

标签: sql linq odata wcf-data-services


【解决方案1】:

WCF 数据服务使您可以访问 DataServiceContext 实例。如果您已经生成了您的参考资料,这将为您输入。但是,您可用的查询运算符是有限的,与仅使用 Entity Framework 和 Linq to Entities 相比,我希望您在尝试使用它时会遇到不同程度的摩擦。

我希望这是因为虽然我使用的数据模型与您的数据模型略有不同,但它是一个类似的分层模型,并且我像您一样从较低的位置开始查询:

var query = context.DataSources.
Where(x => x.ReportLayouts[0].ReportLayoutID == 1045 &&  x.InstanceName == "hello").
Select(li => new { InstanceName = li.InstanceName });

ToList() 上的结果

发生“System.NotSupportedException”类型的未处理异常 在 Microsoft.Data.Services.Client.dll 中

附加信息:表达式 (([10007].ReportLayouts.get_Item(0).ReportLayoutID == 1045) 和 ([10007].InstanceName == "hello")) 不受支持。

为了获得该数据,我随后尝试了以下测试:

var query2 = context.DataSources.Select(x => x.ReportLayouts[0].ReportLayoutID == 1045);
var result2 = query2.ToList();

'System.NotSupportedException' 附加信息:方法 不支持“选择”。

然后我从我的顶级实体开始,相当于你的 Person 并运行了这个:

var query3 = context.Reports.Where(x =>x.ReportLayoutID == 34 &&  x.DatabaseInstance.ServerName == "hello");
var result3 = query3.ToList();

这很好用。我现在正在努力通过导航属性从这个顶级实体到较低级别的实体。直接使用 DataServiceContext 类,我可以更轻松地编写一个 DataServiceQuery,它可以直接转换为带有 AddQueryOption 的 ODATA 支持的 URL 格式:

query = query.AddQueryOption("$expand", expandPropertyName);

这允许您通过生成类似于此的 url 显式加载导航属性:

ReportService.svc/DataSources?expand=dataobjects

生成的服务引用还提供对 DataServiceContext.LoadProperty 方法的访问。加载后,您可以查询它,但这涉及往返。

就我个人而言,我不会将 WCF 数据服务用作您的 DAL,因为这是构建实体框架的目的。如果您需要使用服务将 EF 模型公开给外部客户端,那就另当别论了,但您的 DAL 仍然应该是实体框架。 WCF 数据服务适用于执行非常简单的 CRUD(无业务逻辑)的应用程序。对于内部作为 DAL 运行的复杂查询,我不会信任它。它支持的 web 方法也非常粗糙,只接受 string 和 int 等原语作为参数。如果需要一项服务,我会调查 WCF,但我怀疑这不是你提到的将它用作 DAL 的情况。

【讨论】:

  • 正是我对将 WCF 数据服务用作 DAL 的风险的想法。当我尝试从 4 个具有其中 3 个条件的不同表中获取数据时,我要么最终向客户端获取太多数据并在客户端对其进行过滤,要么编写一个生成丑陋 sql 的 LINQ 表达式。前任。在我的原始数据模型中,如果我有一个额外的列 ShippingPriority for LineItems talble,并且我想获取一个人订购的所有订单项,其运输优先级为“2 天”,我如何才能获得它oDataCOntext.Orders.where( o => o.PersonId==1 && ).Select(o=>new{Li=oi.LineItems})并在客户端过滤它。跨度>
  • @SriHarshaVelicheti 我假设你的 lineItems 将是空的。获取lineItems,默认不会返回,看这篇文章msdn.microsoft.com/en-us/library/ee358709(v=vs.110).aspx
【解决方案2】:

如果您想更好地控制 OData 通信,我建议您使用更匹配 OData 协议的库。您可以查看我的文章“使用 Simple.OData.Client 使用 OData 提要的 12 个理由”,其中我提出了使用 WCF 数据服务的一些挑战(尤其是涉及多个实体时)以及为什么 Simple.OData.Client 更适合.这是链接:

http://www.codeproject.com/Articles/686240/12-reasons-to-consume-OData-feeds-using-Simple-ODa

【讨论】:

    【解决方案3】:

    在某些情况下你会发现你无法在 LinQ 中生成 Odata 查询,并不是不能查询,只是 Linq 提供者做不到。在我们的项目开始时,我们很快发现自己首先编写了 Odata 查询,然后尝试将其转换为 LinQ;没过多久,我们就简单地使用 Odata 进行查询。

    这篇文章可能会为您提供一些其他有用的信息:Disadvantages of OData? 特别是关于使用视图的链接帖子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多