BuildNotContainsExpression вызывает System.StackOverflowException с большим набором данных в Windows 7 - 64-разрядный - PullRequest
0 голосов
/ 16 декабря 2010

Я столкнулся с условием сбоя моего приложения с определенным набором данных в Windows 7, 64-разрядной версии.Все остальные платформы отлично работают на одном наборе данных.Я определил, что мое приложение аварийно завершает работу в выражении BuildNotContainsExpression, которое опубликовали многие люди.

Есть ли способ для построения выражения с использованием памяти из кучи?
Должен ли я просто разбить готовый список пользователейи обрабатывать меньшие порции за раз (например, 1000)?
Что-то еще?

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);
}

Редактировать: вот функция BuildNotContains - она ​​не рекурсивная:

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, equal));
        return Expression.Lambda<Func<TElement, bool>>(body, p);
    }

Вот соответствующая часть моей диаграммы EDMX: alt text

1 Ответ

0 голосов
/ 16 декабря 2010

EF 4 не требует BuildContainsExpression, вы используете более раннюю версию?

Похоже, вы пытаетесь объединить две таблицы, чтобы найти пропущенные идентификаторы, но вместо этого вы делаете все это на стороне клиентана на сервере SQL.

Вместо этого используйте объединение между двумя таблицами, чтобы найти снимки таблиц, у которых нет соответствующего пользователя.См., Например, http://www.hookedonlinq.com/OuterJoinSample.ashx

Если между двумя вашими таблицами были отношения FK, вы можете выбрать записи для удаления с помощью простого!. Любая (...) оговорка.

...