使用LINQ to SQL从存储过程中获取多维结果

时间:2009-06-09 16:18:43

标签: linq linq-to-sql stored-procedures

我正在使用LINQ to SQL来调用带有单个结果集的存储过程(我已经找到了很多关于处理多个结果集的信息,但这不是我正在做的事情)。结果集实际上是连接在一起的3个表中的所有列,并且我有3个表的LINQ to SQL实体。架构是这样的:

  • 客户1
    • 订单1
      • 产品1
      • 产品2
      • 产品3
    • 订单2
      • 产品4
  • 客户2
    • 订单3
      • 产品5
    • 订单4
      • 产品6
      • 产品7

基本上,1个客户到多个订单,1个订单到很多产品。因此,存储过程的结果集实际上是每个产品一行,但每行包括所有Order和Customer列。在上面的例子中,存储过程将返回7行。

所以问题是:如何从LINQ to SQL中获取2个Customer对象,每个对象都填充了Orders集合,并且每个Order对象的Products集合都填充了存储过程的结果?

我知道如果你做的事情(dc是LINQ to SQL DataContext)......

var options = new DataLoadOptions();
options.LoadWith<Customer>(c => c.Orders);
dc.LoadOptions = options;

var customers = from c in dc.Customers select c;

...然后观察生成的SQL,它实际上会运行一个将Customers连接到Orders的SQL语句,从两者中选择所有列,然后返回填充了Orders集合的不同Customer对象。我想要对对象进行同样的翻译,但是从我的存储过程的结果开始。

我已经尝试将存储过程的返回类型设置为Customer,但是通过上面的示例,我得到了7个Customer对象(5个重复项)的集合,这些对象没有填充Orders集合。如果我然后迭代其中一个Customer对象的Orders集合,我看到它们是懒惰加载到数据库的另一次往返。然后我尝试将返回类型设置为Product,并且我确实获得了7个产品,但是如果我尝试访问它们,则它们的Order属性通过另一个往返延迟加载。

我还尝试将结果视为IMultipleResults,调用GetResult&lt; Customer&gt;()和GetResult&lt; Order&gt;()和GetResult&lt; Product&gt;()并手动将它们拼接在一起。但是,在这种情况下,只有第一次调用GetResult&lt;&gt;()才会返回一些内容(三种实体类型中的任何一种都可以使用,但仅适用于第一次GetResult&lt;&gt;()调用)。第二个和第三个GetResult&lt;&gt;()调用返回null。

感谢任何人提供的任何帮助。我一直在想我要么丢失一些简单的东西,要么LINQ to SQL没有提供任何公共API来执行此操作(即使它似乎在上面的LoadsWith示例中单独执行此操作)。

1 个答案:

答案 0 :(得分:0)

我能想出的最佳解决方案是:

  1. 修改sproc以实际返回多个结果集(上例中的Customers,Orders和Products)
  2. 在LINQ to SQL方面像往常一样使用IMultipleResults(有很多文档和示例)来获取这3个独立的IEnumerables
  3. 创建每个非根实体的分组集合,即var groupedOrders = allReturnedOrders.GroupBy(order => order.CustomerID)var groupedProducts = allReturnedProducts.GroupBy(p => p.OrderID)
  4. 循环遍历非叶对象并使用EntitySet.SetSource()方法填充其关联对象的集合,即customer.Orders.SetSource(groupedOrders.Single(orderGroup => orderGroup.Key == customer.CustomerID)
  5. 这会从内存中的DBML中获取您常用的实体对象,而且代码不是很多(您正在创建的层次结构中每层有2-3行)。它确实涉及修改sproc,但它实际上应该减少数据库中的数据传输,因为你没有重复所有更高级别的数据,如加入所有表所做的(在上面的例子中重复每个Product的Customer和Order列)