【问题标题】:C# Converting List throwing exception in linq queryC# 转换列表在 linq 查询中抛出异常
【发布时间】:2016-10-13 10:21:06
【问题描述】:

我有一个关于列表到列表问题的问题。

我的模特:

public partial class OrderDetail
{
    public int Id { get; set; }
    public int OrderId { get; set; }
    public string SparePartName { get; set; }
    public Nullable<decimal> SparePartPrice { get; set; }
    public Nullable<decimal> Labor { get; set; }
    public Nullable<decimal> Total { get; set; }
    public string Comment { get; set; }
}

public partial class Orders
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public int StorageId { get; set; }
    public int UserId { get; set; }
    public Nullable<System.DateTime> DateEntry { get; set; }
    public Nullable<System.DateTime> DateRelease { get; set; }
    public Nullable<System.DateTime> DateEstimatedRelease { get; set; }
    public Nullable<System.DateTime> DateUpdate { get; set; }
    public Nullable<decimal> Price { get; set; }
    public int Status { get; set; }
    public string FollowCode { get; set; }
    public string DeviceBrand { get; set; }
    public string DeviceModel { get; set; }
    public string DeviceSerialNumber { get; set; }
    public string DeviceComplaint { get; set; }
    public string Comment { get; set; }
}

我的视图模型:

public class VMOrderEdit
{
    public int Id { get; set; }
    public int StorageId { get; set; }
    public int UserId { get; set; }
    public string StorageName { get; set; }
    public string CustomerName { get; set; }
    public string CustomerTelephone { get; set; }
    public DateTime? DateEntry { get; set; }
    public DateTime? DateUpdate { get; set; }
    public DateTime? DateRelease { get; set; }
    public DateTime? DateEstimatedRelease { get; set; }
    public decimal? Price { get; set; }
    public string StatusName { get; set; }
    public string FollowCode { get; set; }
    public string DeviceBrand { get; set; }
    public string DeviceModel { get; set; }
    public string DeviceSerialNumber { get; set; }
    public string DeviceComplaint { get; set; }
    public string Comment { get; set; }
    public int MyProperty { get; set; }
    public List<VMOrderEditDetails> Details { get; set; }
}
public class VMOrderEditDetails
{
    public int Id { get; set; }
    public int OrderId { get; set; }
    public string SparePartName { get; set; }
    public decimal SparePartPrice { get; set; }
    public decimal Labor { get; set; }
    public decimal Total { get; set; }
    public string Comment { get; set; }
}

我的控制器:

List<VMOrderEdit> OrderEditObj = (from o in DB.Orders
                                  join sn in DB.OrderStatusName on o.Status equals sn.Id
                                  join st in DB.Storages on o.StorageId equals st.Id
                                  join c in DB.Customers on o.CustomerId equals c.Id
                                  where o.Id == Id
                                  select new VMOrderEdit()
                                  {
                                      Id = o.Id,
                                      StorageId = o.StorageId,
                                      StorageName = st.Name,
                                      UserId = o.UserId,
                                      CustomerName = c.NameSurname,
                                      CustomerTelephone = c.Telephone,
                                      DateEntry = o.DateEntry,
                                      DateUpdate = o.DateUpdate,
                                      DateRelease = o.DateRelease,
                                      Price = o.Price,
                                      StatusName = sn.Name,
                                      FollowCode = o.FollowCode,
                                      DeviceBrand = o.DeviceBrand,
                                      DeviceModel = o.DeviceModel,
                                      DeviceSerialNumber = o.DeviceSerialNumber,
                                      DeviceComplaint = o.DeviceComplaint,
                                      Comment = o.Comment,
                                      Details = DB.OrderDetail.Where(x => x.OrderId == o.Id).ToList()
                                      }
                               ).ToList();

在这一行:

Details = DB.OrderDetail.Where(x => x.OrderId == o.Id).ToList()

visual studio 给出这个错误:

不能隐式转换类型 'System.Collections.Generic.List' 到 'System.Collections.Generic.List

我该如何处理这个错误?

【问题讨论】:

  • DetailsVMOrderEditDetails 列表,而DB.OrderDetail 是(我假设)OrderDetail 可枚举的。
  • 问题是,你想在'Details'中存储什么'OrderDetails',然后做一个嵌套选择来填充'Details'属性,然后是ToList()

标签: c# asp.net-mvc entity-framework linq


【解决方案1】:

您试图将OrderDetail 列表分配给VMOrderEditDetails,这注定会失败。

您的 LINQ 查询应如下所示。我还没有对 Select 进行可空检查和转换。它可以由您完成,并且非常简单。如果有帮助,请标记为答案。

 Details = DB.OrderDetail.Where(x => x.OrderId == o.Id).Select(x=>new VMOrderEditDetails{
    Id = x.Id,
    OrderId = x.OrderId,
    SparePartName = x.SparePartName,
    SparePartPrice = x.SparePartPrice,
    Labor = x.Labor,
    Total = x.Total,
    Comment = x.Comment
}).ToList()

【讨论】:

  • 感谢您的努力和时间。
【解决方案2】:

DB 返回一个OrderDetails 的对象,但Details 列表属性中的项目是VMOrderEditDetails 类型的..

必须在分配之前将每个项目从 OrderDetails 转换为 VMOrderEditDetails

  1. 您可以在 .Where 之后添加 .Select 以转换为该行中 .ToList() 之前的类型,但 除外(参见选项 2 的代码)

    Details = DB.OrderDetail.Where(x => x.OrderId == o.Id)
                            .Select(x => new VMOrderEditDetails { /* your conversion*/})
                            .ToList()
    
  2. 更好的解决方案是在此之前添加一个额外的GroupJoin,然后只在.Select 中进行转换,而不是检索数据:

    List<VMOrderEdit> OrderEditObj = (from o in DB.Orders
                                      join sn in DB.OrderStatusName on o.Status equals sn.Id
                                      join st in DB.Storages on o.StorageId equals st.Id
                                      join c in DB.Customers on o.CustomerId equals c.Id
                                      join d in DB.OrderDetails on o.Id equals d.OrderId into d 
                                      where o.Id == Id
                                      select new VMOrderEdit()
                                      {
                                          Id = o.Id,
                                          StorageId = o.StorageId,
                                          //All the other properties
                                          Comment = o.Comment,
                                          Details = d.Select(x => new VMOrderEditDetails{ /*your convertion*/ }).ToList()
                                      }).ToList();
    
  3. 因为您使用的是实体框架,所以更好的选择是 用导航属性替换所有joins,然后仍然在底部进行转换。

【讨论】:

  • 感谢您的努力和时间。
  • @ysrtymz - 不客气 :) 它有助于您理解问题吗?
  • 是的,很清楚。我试图使用一个无法识别/调用/创建的列表对象.. 对吗?
【解决方案3】:

这样试试,

Details = DB.OrderDetail.Where(x => x.OrderId == o.Id)
            .Select(x => new VMOrderEditDetails {
                       Id = x.Id,
                       OrderId = x.OrderId,
                       SparePartName = x.SparePartName,
                       SparePartPrice = x.SparePartPrice.Value,
                       Labor = x.Labor.Value,
                       Total = x.Total.Value,
                       Comment = x.Comment
                   }).ToList()

【讨论】:

  • 感谢您的努力和时间。
  • @ysrtymz,x.Labor 是可以为空的类型,需要 x.Labor.Value 但如果没有 .value,答案在上面标记为接受?
  • 我想通了。谢谢你的警告。我用“十进制?”更新了我的 ViewModel?
【解决方案4】:
DB.OrderDetail
  .Where(x => x.OrderId == o.Id)
  .ToList()

应该是

DB.OrderDetail
  .Where(x => x.OrderId == o.Id)
  .Select(x => new VMOrderEditDetails () 
  { 
      Id = x.OrderId
  })
  .ToList<VMOrderEditDetails>()

因为types 不同

【讨论】:

    【解决方案5】:

    DetailsList&lt;VMOrderEditDetails&gt; 类型,但您正尝试为其分配 List&lt;OrderDetail&gt; 值,所以要这样设置

    Details = DB.VMOrderEditDetails.Where(x => x.OrderId == o.Id).ToList()
    

    【讨论】:

    • DB.VMOrderEditDetails 肯定不存在,因为 VMOrderEditDetails 是一个 ViewModel 类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    • 2015-09-02
    • 2020-03-12
    • 2015-09-13
    相关资源
    最近更新 更多