【问题标题】:Linq query returning null when trying to pass a column value from list object尝试从列表对象传递列值时,Linq 查询返回 null
【发布时间】:2013-10-25 13:41:04
【问题描述】:

Linq 查询在尝试传递从列表对象中获取的列值时返回 null。是否可以按照代码中的方式进行操作。期待答案或建议。

var query = from p in context.ProcessStepTables
            where (p.DiagramID == diagramInfo.DiagramID)
            orderby p.ProcessNo select new{
                  DiagramProcessID = p.DiagramProcessID,
                  ProcessNo = p.ProcessNo,
                  ProcessID = p.ProcessID,
                  ProcessName = Process().Find(x => 
                           p.ProcessID == x.ProcessID).ProcessName.ToString(),
                  MakerName = Maker().Find(x=>
                           p.MakerID==x.MakerID).MakerName.ToString(),
                  Price = p.Price,
                  Note = p.Note,
                  Notice = p.Notice
            };

private List<MakerTable> Maker()
{
   List<MakerTable> pList = new List<MakerTable>();
   try
   {
       IQueryable<MakerTable> maker = (from data in context.MakerTables
                                       select data) as IQueryable<MakerTable>;
       foreach (MakerTable val in maker)
       {
          pList.Add(val);
       }
       return pList.OrderBy(x => x.MakerName).ToList();

    }
    catch (Exception ex)
    {
       MessageBox.Show(ex.Message);
       return null;
    }
}

【问题讨论】:

  • 代码在哪里返回null?
  • 消息是什么?我可以看到由于某些异常,返回值可能是null。最好删除或注释掉所有的try-catch 块来调试它。
  • Sorry Query is Exception "LINQ to Entities 无法识别方法 'System.String ToString()' 方法,并且此方法无法转换为存储表达式。" var 查询部分返回异常!
  • 您的 Maker 方法的整个定义可以只用一行替换,即return context.MakerTables.OrderBy(x=&gt;x.MakerName).ToList();
  • 你试过没有 2 个.ToString() 调用吗?

标签: c# wpf linq c#-4.0


【解决方案1】:

这是因为,您的提供者不知道 .ToString() 方法,即,当您以 IQueryable 形式创建查询时,它会被转换为等效的 SQL 查询,因此如果您包含任何 C# 函数,则事件是非原始的数据类型,它会抛出该错误,因为您的查询构造如下:

"Select s.DiagramProcessID as DiagramProcessID, ...other fields..
 from MakerTables s where something.ToString()=='anyvalue'"

很明显,sql 对.ToString() 一无所知。

避免的简单方法是,在将.ToList() 应用于您的查询之后,执行您的自定义选择。

当您这样做或.AsEnumerable() 时,会在数据库上执行查询,现在任何自定义选择或 where 子句都会在 CLR 上进行翻译

试试这个:

var query = context.ProcessStepTables
            .Where(s=>s.DiagramID == diagramInfo.DiagramID)
            .OrderBy(s=>s.ProcessNo)
            .ToList() //this will cause the query to be executed on the db
             //Now perform the selection on returned result set, now the linq
             //has to do with this dataset
            .Select(s=>new
             {
                   DiagramProcessID = s.DiagramProcessID,
                   ProcessNo = s.ProcessNo,
                   ProcessID = s.ProcessID,
                   //other items in your custom list
             });

你也可以用下面的方法替换你的 Maker 方法:

private List<MakerTable> Maker()
{
    try
    {
       return context.MakerTables.OrderBy(x=>x.MakerName).ToList();
    }
    catch (Exception ex)
    {
       MessageBox.Show(ex.Message);
       return null;
    }
}

【讨论】:

    【解决方案2】:

    分步检查空值,第一步是查询,然后消费者需要检查 Marker 是否包含有效值:

    var query = from p in context.ProcessStepTables
                where (p.DiagramID == diagramInfo.DiagramID)
                orderby p.ProcessNo
                select new{
                            DiagramProcessID = p.DiagramProcessID,
                            ProcessNo = p.ProcessNo,
                            ProcessID = p.ProcessID,
                            ProcessName = Process().Find(x => p.ProcessID == x.ProcessID).ProcessName.ToString(),
                            Marker = context.MakerTables
                                            .OrderBy(itm => itm.MakerName)
                                            .FirstOrDefaut(itm => itm.MakerID==x.MakerID))
    ;
    

    在某些情况下,找不到某些东西,而 find 会引发异常。在尝试从 Marker 的属性中提取值之前,最好在 Marker检查上述代码是否为空

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 2018-06-09
      • 1970-01-01
      • 2014-01-08
      • 2021-07-21
      • 1970-01-01
      相关资源
      最近更新 更多