2014-09-16 6 views
0

У меня есть простой запрос. Метод-1 работает хорошо. Но я не понимаю, что не так с методом-2?запрос linq со списком

// метод-1

 List<string> li = new List<string>(); 
     List<string> liSNB = new List<string>(); 
     li.Add("result1"); 
     li.Add("result2"); 
     li.Add("result3"); 
     var vQuery = from ssoli in li.AsEnumerable() 
        where li.Contains(ssoli) 
        where ssoli.Contains("2") 
        select new 
        { 
         soName = ssoli, 
        }; 

     liSNB.Clear(); 
     foreach (var v in vQuery) 
      liSNB.Add(v.soName); 
     li.Clear(); 
     li.AddRange(liSNB); 
     lbxLinq.Items.AddRange(li.ToArray());//add results2 

// метод-2

 List<string> liSNB = new List<string>(); 
     liSNB.Add("result1"); 
     liSNB.Add("result2"); 
     liSNB.Add("result3"); 
     var vQuery = from ssoli in liSNB.AsEnumerable() 
        where liSNB.Contains(ssoli) 
        where ssoli.Contains("2") 
        select new 
        { 
         soName = ssoli, 
        }; 

     liSNB.Clear(); 
     foreach (var v in vQuery) 
      liSNB.Add(v.soName); 
     lbxLinq.Items.AddRange(liSNB.ToArray());//add nothing WHY??? 

Почему нет результатов в методе-2 почему? В этой ситуации я работал в течение 2 дней. Это ошибка или что-то еще? Спасибо за ответы изначально.

+1

Вы слышали о отсроченном исполнении LINQ? 'liSNB.Clear();' очищает список, который также «очистит» не выполненный запрос. Вы можете сохранить его через 'ToList'. –

+0

нет, я еще не слышал. это об этой ошибке? – lotomax

+0

Благодарим вас за помощь – lotomax

ответ

0

Linq запрос выполняется, когда результат доступен, так что вам нужно позвонить ToArray() или ToList() после запроса:

var vQuery = (from ssoli in liSNB.AsEnumerable() 
       where liSNB.Contains(ssoli) // this line is pointless because you are checking in same list 
       where ssoli.Contains("2") 
       select new 
       { 
       soName = ssoli, 
       }).ToList(); 

Теперь ваши запрос будет выполнен, когда вызывается ToList(), и результат будет в vQuery.

Строка where liSNB.Contains(ssoli) не требуется, поскольку вы проверяете элемент списка источников в списке источников, поэтому все элементы будут отфильтрованы, что означает, что фильтрация не будет применяться.

+0

Стоит упомянуть, что 'where liSNB.Contains (ssoli)' бессмысленно, поскольку он проверяет каждую строку в списке, если она в списке. –

+0

Как и 'AsEnumerable'. Как выбирает вещи из списка, строит список результатов, очищает исходный список, копирует все из списка результатов в исходный список и копирует все из исходного списка в окончательный список. 'Добавить ToList в конец запроса' очень редко является удовлетворительным ответом. – Rawling

+0

в том, что я использую много запросов, подобных тому, где мне нужен liSNB.Contains (ssoli). Вы очень правы для этого кода, но я сокращаю свой код для этого вопроса. Ответы Эхсана теперь работают для меня. Спасибо – lotomax

1

Поскольку LINQ использует отложенное выполнение, ваш запрос actualy выполнение здесь:

foreach (var v in vQuery) 

В вашем втором фрагменте кода вы удаляете все элементы из liSNB перед выполнением query.So он не возвращает что-нибудь.

Btw это не имеет никакого смысла, вы можете удалить его:

where liSNB.Contains(ssoli) 

Вы можете прочитать больше о отсроченном исполнении в here и here

+0

спасибо за ответ – lotomax

1

Я буду использовать некоторые ошибки во втором кодовом блоке; большинство из них также относятся к первому блоку.

List<string> liSNB = new List<string>(); 
    liSNB.Add("result1"); 
    liSNB.Add("result2"); 
    liSNB.Add("result3"); 

AsEnumerable в этой строке ничего не дает:

var vQuery = from ssoli in liSNB.AsEnumerable() 

Это Contains проверка ничего не дает - конечно ssoli в списке или он не будет отображаться в запросе:

    where liSNB.Contains(ssoli) 

Это не так:

    where ssoli.Contains("2") 

Там нет причин, чтобы гнездиться строка, которую вы хотите здесь - просто select ssoli будет работать:

    select new 
       { 
        soName = ssoli, 
       }; 

Запрос еще не работает - она ​​откладывается. Сняв список здесь, вы не имеете ничего запрашивать через:

liSNB.Clear(); 

В то время как вы в цикле foreach запрос «работает».Изменив исходный список во время выполнения запроса, вы вызовете запрос на исключение. (Вы также должны удалить soName. здесь, если вы остановили выбор его выше):

foreach (var v in vQuery) 
     liSNB.Add(v.soName); 

(На самом деле в вашем примере у вас есть только один соответствующий пункт, так что вы получаете вместе с ним Если у вас есть два или более пунктов. совпадающий с запросом, в котором у вас возникнут проблемы).

The ToArray бессмысленно здесь:я исправлюсь, метод принимает object[].

lbxLinq.Items.AddRange(liSNB.ToArray()); 
+0

благодарю вас за помощь, но lbxLinq.Items.AddRange (liSNB.ToArray()); необходимо, потому что lbxLinq является ListBox – lotomax

+1

@ user1149492 Достаточно справедливо в последнем пункте. – Rawling

Смежные вопросы