我正在使用 LINQ to SQL 调用具有单个结果集的存储过程(我找到了很多有关处理多个结果集的信息,但这不是我正在做的事情)。结果集实际上是连接在一起的 3 个表中的所有列,并且我有这 3 个表的 LINQ to SQL 实体。架构是这样的:
- 客户 1
- 订单 1
- 产品 1
- 产品 2
- 产品 3
- 订单 2
- 产品 4
- 订单 1
- 客户 2
- 订单 3
- 产品 5
- 订单 4
- 产品 6
- 产品 7
- 订单 3
基本上,1 个客户对应多个订单,1 个订单对应多个产品。因此,存储过程的结果集实际上是每个 Product 一行,但每一行包含所有 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,它实际上会运行一个 SQL 语句,将 Customers 与 Orders 连接起来,从两者中选择所有列,然后返回不同的 Customer 对象,并填充其 Orders 集合。我想要对对象进行同样类型的转换,但是来 self 的存储过程的结果。
我尝试将存储过程的返回类型设置为 Customer,但在上面的示例中,我得到了 7 个 Customer 对象的集合(5 个重复项),这些对象没有填充其 Orders 集合。如果我随后迭代其中一个 Customer 对象的 Orders 集合,我会发现它们是通过另一次往返数据库进行延迟加载的。然后,我尝试将返回类型设置为 Product,并且确实获得了 7 个产品,但如果我尝试访问它们,它们的 Order 属性会通过另一次往返延迟加载。
我还尝试将结果视为 IMultipleResults,调用 GetResult
感谢任何人可以提供的帮助。我一直在想,我要么错过了一些简单的东西,要么 LINQ to SQL 不提供任何公共(public) API 来执行此操作(尽管它在上面的 LoadsWith 示例中似乎是自行执行此操作)。
最佳答案
我能想到的最佳解决方案是:
- 修改存储过程以实际返回多个结果集(上例中的客户、订单和产品)
- 在 LINQ to SQL 端照常使用 IMultipleResults(有大量相关文档和示例)来获取这 3 个独立的 IEnumerable
- 创建每个非根实体的分组集合,即
var groupedOrders = allReturnedOrders.GroupBy(order => order.CustomerID)
和var groupedProducts = allReturnedProducts.GroupBy(p => p.OrderID)
- 循环遍历非叶对象并使用
EntitySet.SetSource()
方法来填充关联对象的集合,即customer.Orders.SetSource(groupedOrders.Single(orderGroup => orderGroup.Key == customer.CustomerID)
这会从内存中的 DBML 获取常用的实体对象,并且代码量并不多(您正在创建的层次结构中每个级别 2-3 行)。它确实涉及修改存储过程,但实际上应该减少从数据库传输的数据,因为您没有像连接所有表那样重复所有更高级别的数据(在上例中为每个产品重复“客户”和“订单”列) .
关于linq - 使用 LINQ to SQL 从存储过程中获取多维结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/971095/