LINQ lambda表达式throws Sequence不包含任何元素

时间:2014-06-24 20:24:55

标签: c# linq lambda

我知道这个错误意味着什么,但我不知道如何在我的LINQ语句中修复它。

ScannerMessages是一本字典。其中的值可以是串行扫描中的数字,也可以是string.empty,或者(在任何扫描发生之前)为null。我有一种感觉,有人会说使用FirstorDefault(),但我不能使用null / string.empty的默认值。我尝试使用

.Any(x => !string.IsNullOrEmpty(x.Value)). 

但这会返回一个bool并且是错误的检查。我觉得我需要一个Where()但我已经尝试过这一点也无济于事(我也试过改变我的GroupBy()子句)。我觉得我很接近,但我不确定在哪里修改我的表达。

注意:这是在一个锁中,所以我知道当我查询它时,我的其他线程都没有影响字典(ScannerMessages被锁定)

    public ScanType equalMessages()
    {
        try
        {
            lock (lckObj)
            {
                if (_scannersPresent)
                {
                    // Check to see if message that came through was caught in the buffer. If it has it will be equal to the previous message.
                    if (ScannerMessages.GroupBy(x => x.Value).Where(x => x.Count() > 1).First().Key == _holdMsg) return ScanType.ClearBuffer;
                    // If all messages are null or empty no scan
                    else if (ScannerMessages.Values.All(s => string.IsNullOrEmpty(s))) return ScanType.NoScan;
                    // If there is only one scanner then all scans must be determined to be either MATNUM or a rescan of an LPN
                    else if (_ScannerCount == 1) return ScanType.DiscernScanType;
                    // If distinct count of non null/empty values is less than total count of all non null/empty values, then scan is good
                    else if (ScannerMessages.Values.Distinct().Count(v => !string.IsNullOrEmpty(v)) < ScannerMessages.Values.Count(v => !string.IsNullOrEmpty(v)))
                    {
                        // This condition is only met if there is more than one of the same scan, and therefore is not a reprint. Pad all values with '0's for proper MATNUM format
                        ScannerMessages = ScannerMessages.Where(x => !string.IsNullOrEmpty(x.Value)).ToDictionary(x => x.Key, x => x.Value.PadLeft(18, '0'));
                        return ScanType.GoodScan;
                    }
                    // If non null/empty counts is equal to one, and the message is not the same as previous scan, then message was not from buffer and is LPN for reprint
                    else if ((ScannerMessages.Values.Distinct().Count(v => !string.IsNullOrEmpty(v)) == 1) && (ScannerMessages.GroupBy(x => x.Value).Where(x => x.Count() > 1).First().Key != _holdMsg)) return ScanType.Reprint;
                    else return ScanType.NoScan;
                }
                return ScanType.NoScan;
            }
        }
        catch (Exception ex) {
            myEvents.raiseErrorMessageBox(ex.Message);
            throw new Exception(ex.Message, ex); }
    }

编辑:我不确定哪一行引发了错误 - 我认为它是第一个if行最后的else如果在else返回ScanType.NoScan之前。这些是使用First()调用的唯一语句。问题是大约每半秒调用一次,因此调试它会备份。有3个线程访问ScannerMessages字典,然后调用此字符的线程检查该字典。当我有4个线程命中它时,我不确定如何调试它。我唯一知道的是它是*线程安全的:/如果我试图在第一行放置一个断点,它会击中很多次,而当我踩到时我会错过任何“真正的”扫描。

2 个答案:

答案 0 :(得分:1)

ScannerMessages.GroupBy(x => x.Value).Where(x => x.Count() > 1).First()

那么如果没有包含多于1个元素的组呢?您认为应该怎么做?

您应该将这些条件分成更小的步骤,而不是试图将所有内容都放在单个表达式中。在这种情况下,我建议使用FirstOrDefault并将条件替换为:

var value = ScannerMessages.GroupBy(x => x.Value).Where(x => x.Count() > 1).FirstOrDefault()
if (value != null && value.Key == _holdMsg) return ScanType.ClearBuffer;

答案 1 :(得分:0)

我不知道我是否需要重新提出这个问题,但我能够使用这个 - 如果对#34;精简&#34;有任何修改。它会很棒 - 我觉得抓住kvp.Value.Vlaue有点多余,但我又不知道怎么回答&#34;问题具体来说,这就是我所需要的。

class testing
{

    private Dictionary<string, string> dict = new Dictionary<string, string>();
    private Dictionary<string, string> _dict = new Dictionary<string, string>();
    private Dictionary<string, string> __dict = new Dictionary<string, string>();
    public testing() 
    {
        dict.Add("stringA", string.Empty);
        dict.Add("stringB", "123456");
        dict.Add("stringC", string.Empty);

        _dict.Add("stringA", string.Empty);
        _dict.Add("stringB", string.Empty);
        _dict.Add("stringC", string.Empty);

        __dict.Add("stringA", "654321");
        __dict.Add("stringB", "123456");
        __dict.Add("stringC", string.Empty);

        checkDict(dict, "dictionary1");
        checkDict(_dict, "dictionary2");
        checkDict(__dict, "dictionary3");


    }

    private void checkDict(Dictionary<string,string> myDict, string s)
    {
        try
        {
            var exam = dict.Where(x => !string.IsNullOrEmpty(x.Value)).ToDictionary(x => x.Key);
            foreach (var kvp in exam)
            {
                Console.WriteLine(kvp.Value.Value);

            }
        }
        catch(Exception ex)
        {
            eh(ex);
        }
    }

    private void eh(Exception ex)
    {
        Console.WriteLine(ex.Message);
        if (ex.InnerException != null) eh(ex.InnerException);
    }
}