Reputation: 55
I am scratching my head on this. The code below I would think should produce the same results. However, they don't. I am clearly missing something. The LINQ query returns a long that is smaller than the plain C# code does.
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;
}
When I run them against the same list:
GetListSizeForCurrentItems: 2401408086
GetListSizeForCurrentItems2: 2401408086
GetListSizeForItemVersions: 459902667
GetListSizeForItemVersions2: 459902667
GetListSize: 459902667
GetListSize2: 2842896668
Refactored code to isolate each query in the above:
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;
}
The change to Concat() definitely changes results.
An extra set of eyes would be beneficial. What am I missing in translating the plain C# into LINQ.
Upvotes: 1
Views: 156
Reputation: 26
In GetListSize2() you don't check if long.TryParse has return false.
The TryParse method is like the Parse method, except the TryParse method does not throw an exception if the conversion fails.It eliminates the need to use exception handling to test for a FormatException in the event that s is invalid and cannot be successfully parsed.
So, if there are some non numeric data in your list, the fileSize won't be 0 but will be the filesize of the previous iteration.
The correction would be :
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;
}
Upvotes: 0
Reputation: 157108
I guess the problem is in the Union
. It returns... (emphasis mine)
An
IEnumerable<T>
that contains the elements from both input sequences, excluding duplicates.
So if you have duplicates in your list, you are only counting unique values. Use Concat
instead.
Upvotes: 2