【问题标题】:How can I use LINQ to Entities (with a transform) to return a nested dataset?如何使用 LINQ to Entities(带有转换)返回嵌套数据集?
【发布时间】:2012-01-12 00:34:18
【问题描述】:

我正在将实体对象转换为我自己的模型(CustomerModel 和 OrderModel)。

我目前有一个返回客户的 IQueryable 方法:

IQueryable<CustomerModel> GetCustomers()
{
    return from c in entities.Customers
           select new CustomerModel {
               CustomerId = c.CustomerId,
               CustomerName = c.CustomerName
               // Orders = ??
           };
}

在我的 CustomerModel 中,您可以看到我有一个 Orders 数组。

class CustomerModel {
    public int CustomerId { get; set; }
    public string CustomerName { get; set; }
    public OrderModel[] Orders { get; set; }
}

class OrderModel {
    public int OrderId { get; set; }
    public int CustomerId { get; set; }
    public string OrderDetails { get; set; }
}

当 Orders 类型为 Array 时,我似乎无法弄清楚如何在 Customer 对象中设置 Orders。

当我将 CustomerModel 的 Orders 更改为 IEnumerable 而不是数组并且您不能将 .ToArray() 与 LINQ to Entities 一起使用时,我能够做到这一点,所以我被卡住了。

所以我的问题是:这可以使用订单数组吗?

问题解答:

  • 为什么是数组?我在别处返回了一个数组(供其他项目使用),让 Orders 也成为一个数组是有意义的。

此外,您不能对订单使用 ToArray(),会引发此错误:

System.NotSupportedException: LINQ to Entities does not recognize the method 'Proj.Models.Orders[] ToArray[Orders](System.Collections.Generic.IEnumerable`1[Proj.Models.Orders])' method, and this method cannot be translated into a store expression.

【问题讨论】:

  • 为什么要一个数组?首先,您可以使用 Enumerable 或 Queryable 中的 .ToArray(),但数组暗示了一些东西(如排序和可变性),这使得 L2E 很难跟踪。

标签: c# .net linq linq-to-entities


【解决方案1】:

如果您的Orders 可以从Customers 访问,您可以尝试:

IQueryable<CustomerModel> GetCustomers()
{
    return from c in entities.Customers
           select new CustomerModel {
               CustomerId = c.CustomerId,
               CustomerName = c.CustomerName
               Orders = from o in c.Orders
                        select new Order{
                            OrderId = o.OrderId,
                            ...
                        }
           };
}

这需要您将Customer.Orders 更改为IEnumerable&lt;Order&gt;。这是在一个请求中加载对象图到数据库的唯一方法。

【讨论】:

  • 我相信你可能是对的。我有一种感觉 IEnumerable 是唯一的方法。谢谢。
【解决方案2】:

当我们的数据访问方法返回业务对象(模型)时,这不是很好的做法。例如,您可以通过以下方式编辑查询:

IQueryable<Customer> GetCustomers()
{
    return entities.Customers;
}

IQueryable<Order> GetOrders()
{
    return entities.Orders;
}

IEnumerable<CustomerModel> GetCustomerModels()
{
    var result = from c in GetCustomers()
                 let orderModels = from o in GetOrders() 
                                   where o.CustomerId == c.CustomerId
                                   select new OrderModel
                                   {....}
                 select new CustomerModel  
                 {
                     CustomerId = c.CustomerId,
                     CustomerName = c.CustomerName,
                     Orders = orderModels.ToArray()
                 }; 
    return result;
}

如果此解决方案对您没有用,请描述您的“实体”

【讨论】:

  • IQueryable 方法位于一个特殊的存储库中。返回的模型也在存储库级别。原因是使实际的 ADO.NET 实体保持私有。另一个原因是我们可以在不影响任何代码的情况下换掉背面。
  • 您不能使用 LINQ to Entities 调用 ToArray()!这是导致的错误:System.NotSupportedException:LINQ to Entities 无法识别方法'Proj.Models.Orders[] ToArray[Orders](System.Collections.Generic.IEnumerable`1[Proj.Models.Orders])'方法,并且该方法不能翻译成商店表达式。
  • 在这种情况下,您必须首先对您的实体进行枚举。这不是一个好主意,但仍然......您能详细描述您的客户实体吗?
  • 实体是为这个例子组成的。但它们将位于各自的 MS SQL 表中,使用 ADO.NET 实体和 LINQ to SQL 访问。客户到订单的关系是一对多的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
  • 1970-01-01
  • 2016-04-08
  • 2011-04-08
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
相关资源
最近更新 更多