-3

我有一些用于处理运行缓慢的 XML 文件的代码。有问题的代码如下。
第一个查询应该从一组大约 1,000 条记录中获取零条或一条记录。如果我得到一个,然后我使用来自第一个结果的 keyID 从另一组(保存大约 2,000 条记录)中提取所需的记录。然后,如果找到该记录,我将把三个值分配给我正在创建的新对象。

我在 VS2015 中检查性能(执行时间)时发现,所有这些语句总共花费了大约 330 毫秒。具体来说,每个值的分配(例如 MatProfileCall.MatSizeText = mss.First().MatSizeText;)每个花费大约 80 毫秒。然后我在两个查询中添加了一个 .ToArray() 到 vars 中。所有代码的执行时间都下降到不到 40 毫秒。

所以我的问题是,在这种情况下,基于另一个 Linq 查询的 Linq 查询中的值分配实际上每次都必须运行这两个查询吗?如果这是真的,那么无论何时您使用查询结果将值分配给另一个对象,总有一点将结果放入数组/列表时性能要好得多,因为 Linq 必须执行查询每一次?

var subMatSize = (from d in pInEdiMatTransS where d.EdiSystemMaterialString == retString && d.IsMapToMatSizeID == true && d.IsSubstituteMatType == false select d);
if (subMatSize.Any())
{
   var mss = (from d in pmss where d.MatSizeID == subMatSize.First().DeafultMatSizeID  select d);
if(mss.Any())
{ 
    MatProfileCall.MatSizeText = mss.First().MatSizeText;
    MatProfileCall.MatSizeID = mss.First().MatSizeID;
    MatProfileCall.MatTypeID = mss.First().MatTypeID;
    return Result.Ok<EDIMaterialProFile>(MatProfileCall);
    }
     else
    { return Result.Fail<EDIMaterialProFile>(THC_Constants.sMICEDICONVERTERROR + "IsMapToMatSizeID is True but MatSizeID not found in MaterialSize");  }
}

与 .ToArray() 相同的代码产生更快的代码:

var subMatSize = (from d in pInEdiMatTransS where d.EdiSystemMaterialString == retString && d.IsMapToMatSizeID == true && d.IsSubstituteMatType == false select d).ToArray();
if (subMatSize.Any())
{
   var mss = (from d in pmss where d.MatSizeID == subMatSize.First().DeafultMatSizeID  select d).ToArray();
   if(mss.Any())
   { 
    MatProfileCall.MatSizeText = mss.First().MatSizeText;
    MatProfileCall.MatSizeID = mss.First().MatSizeID;
    MatProfileCall.MatTypeID = mss.First().MatTypeID;
    return Result.Ok<EDIMaterialProFile>(MatProfileCall);
   }
   else
   { return Result.Fail<EDIMaterialProFile>(THC_Constants.sMICEDICONVERTERROR + "IsMapToMatSizeID is True but MatSizeID not found in MaterialSize");  }
}
4

1 回答 1

1

我的猜测是您在第一种情况下重新使用初始查询,但在第二种情况下只查询数组,因此您不会再次重新处理查询:

var subMatSize = (from d in pInEdiMatTransS 
                  where d.EdiSystemMaterialString == retString 
                     && d.IsMapToMatSizeID == true 
                     && d.IsSubstituteMatType == false 
                  select d);

方法一:

var mss = (from d in pmss       V-- subMatSize is a query
           where d.MatSizeID == subMatSize.First().DeafultMatSizeID 
           select d);

在这种情况下,调用First()重新运行subMatSize查询,浪费资源。

方法二:

var mss = (from d in pmss       V-- subMatSize is an array
           where d.MatSizeID == subMatSize.First().DeafultMatSizeID 
           select d);

在这里,您只是要求数组中的第一项,这要快得多。你做了类似的事情,mss但做了三遍。每个First()呼叫一个。

FirstOrDefault通过调用和检查 null 与调用,您可能会获得相似(或更好)的结果Any

var subMatSize = (from d in pInEdiMatTransS 
                  where d.EdiSystemMaterialString == retString 
                     && d.IsMapToMatSizeID == true 
                     && d.IsSubstituteMatType == false 
                  select d);
var firstSubMat = subMatSize.FirstOrDefault();

if (firstSubMat != null)
{
   var mss = (from d in pmss       V-- use variable here
              where d.MatSizeID == firstSubMat.DeafultMatSizeID
              select d);
   var firstmss = mss.FirstOrDefault();

   if(firstmss != null)
   { 
        MatProfileCall.MatSizeText = firstmss.MatSizeText;
        MatProfileCall.MatSizeID   = firstmss.MatSizeID;
        MatProfileCall.MatTypeID   = firstmss.MatTypeID;
        return Result.Ok<EDIMaterialProFile>(MatProfileCall);
    }

所以我的问题是,在这样的代码中,是否从基于另一个 Linq 查询的 Linq 查询中分配值实际上必须每次都运行这两个查询,因此无论何时您使用查询结果将值分配给另一个对象将结果放入数组/列表中总是有一个更好的性能,因为 Linq 每次都必须执行查询?

是的。但是,在这种情况下,您只关心第一个结果,因此您不需要存储整个结果集,只需存储第一个结果集。

于 2017-03-28T19:51:11.127 回答