2015-12-10 3 views
1

Я почесываю голову на этом. Приведенный ниже код, я думаю, должен давать те же результаты. Однако они этого не делают. Мне явно чего-то не хватает. Запрос LINQ возвращает длину, которая меньше, чем обычный код C#.Различные результаты LINQ vs 'normal' C# code

public static long GetListSize(SPList list) 
    { 
     long longInt = 0; 
     long byteSize = (from item in list.Items.OfType<SPListItem>() 
         where item.ParentList.EnableVersioning == false 
         select long.TryParse(item["File_x0020_Size"].ToString(), out longInt) ? longInt : 0) 
       .Concat(from iItem in list.Items.OfType<SPListItem>() 
         where iItem.ParentList.EnableVersioning == true && iItem.Versions.Count > 1 
         from vItem in iItem.Versions.OfType<SPListItemVersion>() 
         select long.TryParse(vItem["File_x0020_Size"].ToString(), out longInt) ? longInt : 0) 
       .Sum(); 

     return byteSize; 
    } 

    public static long GetListSize2(SPList list) 
    { 
     long byteSize = 0; 
     long fileSize = 0; 
     foreach (SPListItem item in list.Items) 
     { 
      if (item.ParentList.EnableVersioning == true && item.Versions.Count > 1) 
      { 
       for (int i = 0; i < item.Versions.Count; i++) 
       { 
        long.TryParse(item.Versions[i]["File_x0020_Size"].ToString(), out fileSize); 
        byteSize += fileSize; 
       } 
      } 
      else 
      { 
       long.TryParse(item["File_x0020_Size"].ToString(), out fileSize); 
       byteSize += fileSize; 
      } 
     } 
     return byteSize; 
    } 

Когда я запускаю их против того же списка:

GetListSizeForCurrentItems: 2401408086
GetListSizeForCurrentItems2: 2401408086
GetListSizeForItemVersions: 459902667
GetListSizeForItemVersions2: 459902667
GetListSize: 459902667
GetListSize2: 2842896668

Refactored код для изоляции каждого запроса в приведенном выше:

public static long GetListSizeForItemVersions(SPList list) 
    { 
     long longInt = 0; 
     long byteSize = (from iItem in list.Items.OfType<SPListItem>() 
         where iItem.ParentList.EnableVersioning == true && iItem.Versions.Count > 1 
         from vItem in iItem.Versions.OfType<SPListItemVersion>() 
         select long.TryParse(vItem["File_x0020_Size"].ToString(), out longInt) ? longInt : 0) 
       .Sum(); 

     return byteSize; 
    } 
    public static long GetListSizeForItemVersions2(SPList list) 
    { 
     long byteSize = 0; 
     long fileSize = 0; 
     foreach (SPListItem item in list.Items) 
     { 
      if (item.ParentList.EnableVersioning == true && item.Versions.Count > 1) 
      { 
       for (int i = 0; i < item.Versions.Count; i++) 
       { 
        long.TryParse(item.Versions[i]["File_x0020_Size"].ToString(), out fileSize); 
        byteSize += fileSize; 
       } 
      } 
     } 
     return byteSize; 
    } 

    public static long GetListSizeForCurrentItems(SPList list) 
    { 
     long longInt = 0; 
     long byteSize = (from item in list.Items.OfType<SPListItem>() 
         where item.ParentList.EnableVersioning == false 
         select long.TryParse(item["File_x0020_Size"].ToString(), out longInt) ? longInt : 0) 
         .Sum(); 
     return byteSize; 
    } 
    public static long GetListSizeForCurrentItems2(SPList list) 
    { 
     long byteSize = 0; 
     long fileSize = 0; 
     foreach (SPListItem item in list.Items) 
     { 
      long.TryParse(item["File_x0020_Size"].ToString(), out fileSize); 
      byteSize += fileSize; 
     } 
     return byteSize; 

    } 

Переход к Concat() определенно меняет результаты.

Дополнительный набор глаз был бы полезен. Что мне не хватает при переводе простого C# в LINQ.

+4

Помимо использования Союза вместо Concat, вы в том числе EnableVersioning == ложных значений в первой части запроса, в то время как в вашем обычном C# кода вы используя «else», чтобы только один элемент мог внести * одну * часть суммы. –

+0

Привет, Джон, ты прав насчет другого (и Союза/Конката). Однако, если я добавлю предложение where в первую часть запроса с EnableVersioning == false, я получаю довольно большую разницу в результатах. Я собираюсь обновить вопрос, чтобы отразить то, что происходит сейчас. – Taoism

+1

Обратите внимание, что нам было бы легче помочь вам, если бы вы могли предоставить короткий, но * полный * пример и удалить все посторонние (например, синтаксический анализ строк - вы уверены, что это даже требуется?) –

ответ

2

Я думаю, проблема в Union. Он возвращается ... (курсив мой)

IEnumerable<T>, который содержит элементы из обеих входных последовательностей, без учета повторов.

Так что, если у вас есть дубликаты в вашем списке, вы считаете только уникальные значения. Вместо этого используйте Concat.

+0

Привет, это дает ответ, в основном, почему номера отключены. У меня все еще есть проблема с итогами, не соответствующими. Я собираюсь обновить вопрос, чтобы понять, как обстоят дела. – Taoism

+0

Он всегда делает :). Вы можете принимать только ответы, а не комментарии. –

0

В GetListSize2() вы не проверяете, если long.TryParse возвращает false.

Метод TryParse похож на метод Parse, за исключением того, что метод TryParse не генерирует исключение, если преобразование завершается неудачно. Это устраняет необходимость использования обработки исключений для проверки исключения FormatException в случае, если s недействителен и не может быть успешно проанализирован.

Итак, если в вашем списке есть некоторые числовые данные, размер файла не будет 0, а будет размером в предыдущую итерацию.

коррекция будет:

public static long GetListSize2(SPList list) 
{ 
    long byteSize = 0; 
    long fileSize = 0; 
    foreach (SPListItem item in list.Items) 
    { 
     if (item.ParentList.EnableVersioning == true && item.Versions.Count > 1) 
     { 
      for (int i = 0; i < item.Versions.Count; i++) 
      { 
       if (long.TryParse(item.Versions[i]["File_x0020_Size"].ToString(), out fileSize) == false) 
        fileSize=0; 
       byteSize += fileSize; 
      } 
     } 
     else 
     { 
      if (long.TryParse(item["File_x0020_Size"].ToString(), out fileSize) == false) 
        fileSize=0; 
      long.TryParse(item["File_x0020_Size"].ToString(), out fileSize); 
      byteSize += fileSize; 
     } 
    } 
    return byteSize; 
} 
+0

Уверены ли вы в этом? ' PS C: \ Users \ XXXX \ Documents> [Int64] $ я = 0 [Пустота] [Int64] :: TryParse ("12", [ссылка] $ я) $ я [Пустота] [ Int64] :: TryParse ("2", [ссылка] $ я) $ я [Пустота] [Int64] :: TryParse ("с", [ссылка] $ я) $ я ' Ughh ... Я не могу заставить его форматировать как сообщение ... но пример, который я сделал в PowerShell, возвращает 0 при анализе альфа ... – Taoism

+0

Невозможно, чтобы предыдущее значение проходило через после вызова TryParse. Метод, который использует параметр out, [требуется для присвоения значения] (https://msdn.microsoft.com/en-us/library/ee332485.aspx) перед его возвратом. В документации [Int64.TryParse] (https://msdn.microsoft.com/en-us/library/zc2x2b1h%28v=vs.110%29.aspx) также четко указано, что значение будет 0, если метод не работает , – pescolino

+0

Извините, вы правы. TryParse переназначить 0, если синтаксический анализ завершился неудачей. – Cristof