BuildNotContainsExpression causes System.StackOverflowException with large data set on Windows 7 -64-bit
I have encountered a condition where my app crashes with a particular dataset on Windows 7, 64-bit. All other platforms work fine on the same dataset. I have determined that my app is crashing in the BuildNotContainsExpression that many people have posted.
Is there a way for the expression to be built using memory from the heap?
Should I just break done my usersActive list and process smaller chunks at a time (like 1000)? Something else?List<int> usersActive = myContext.myTable.Select(a => a.tableUsersSnapshot.id).Distinct().ToList();
// The code blows up (only on Win7 64-bit) on this line when usersActive is large ~4000
// (probably will blow up on all platforms if usersActive is sufficiently large)
expTest = CustomExpressions.BuildNotContainsExpression<tableUsersSnapshot, int>(a => a.id, usersActive);
List<tableUsersSnapshot> usersToDelete = myContext.myTableSnapshot.Where(expTest).ToList();
// Delete the objects in the delete list
foreach(tableUsersSnapshot user in usersToDelete)
{
myContext.DeleteObject(user);
}
Edit: Here's the BuildNotContains function - it is not recursive:
public static Expression<Func<TElement, bool>> BuildNotContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
{
if (null == valueSelector) { throw new ArgumentNullException("valueSelector");}
if (null == values) { throw new ArgumentNullException("values"); }
ParameterExpression p = valueSelector.Parameters.Single();
// p => valueSelector(p) != values[0] && valueSelector(p) != ...
if (!values.Any())
{
return e => true;
}
var equals = values.Select(value => (Expression)Expression.NotEqual(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.And(accumulate, eq开发者_如何学Pythonual));
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
Here's the applicable portion of my EDMX diagram:
EF 4 doesn't require BuildContainsExpression
, are you using an earlier version?
It looks like you are trying to join two tables to find missing Ids but you are doing it all client-side instead of on SQL server.
Instead, use a join between the two tables to find the table snapshots that don't have a corresponding user. See for example http://www.hookedonlinq.com/OuterJoinSample.ashx
If you had an FK relationship between your two tables you could select the records to delete using a simple ! .Any(...) clause.
精彩评论