Нужно знать работу этого кода, который использует AsEnumerable

Когда я запускаю этот код:

return dbAccess.ExecuteDataTable(dbAccess)
               .AsEnumerable()
               .Select(r => r.Field<int>("Id"))
               .ToList();                       

Это дает мне ошибку:

SqlParameter уже находится в коллекции SqlParameterCollection.

Хотя я знаю, что AsEnumerable работает на этой концепции отложенного выполнения или ленивой загрузки, но эта концепция до сих пор не укоренилась в моей голове.

Может ли кто-нибудь объяснить работу AsEnumerable и этого кода?


person Lakshay    schedule 08.03.2014    source источник
comment
Какой тип данных возвращается из ExecuteDataTable?   -  person Scott Chamberlain    schedule 08.03.2014
comment
@ScottChamberlain возвращается таблица данных   -  person Lakshay    schedule 08.03.2014
comment
Проверьте, поможет ли вам это решение. stackoverflow.com/q/6289607/1733852   -  person RKS    schedule 08.03.2014
comment
Код, который вы нам показали, не должен вызывать эту ошибку, вы уверены, что ошибка не происходит внутри ExecuteDataTable?   -  person Scott Chamberlain    schedule 08.03.2014


Ответы (2)


Эквивалент вашего кода следующий

var retVal = new List<int>();
var dataTable = dbAccess.ExecuteDataTable(dbAccess);
foreach(DataRow r in dataTable.Rows)
{
    var rowResult = (int)r["Id"]; //`(int)r["Id"]` is equivalent to `r.Field<int>("Id")`
    retVal.Add(rowResult);
}
return retVal;

Вам не нужно беспокоиться о различном выполнении вашего кода, потому что вы ставите .ToList() в конце, чтобы он запускал код прямо в том месте, которое вы нам показали. Если бы вы упустили это, было бы намного сложнее показать «эквивалентный код» без использования yield return, что могло бы еще больше запутать вас.

Как сказано выше, единственное, что в приведенном выше коде может вызвать вашу ошибку, которую я вижу, это dbAccess.ExecuteDataTable(dbAccess);. Попробуйте переписать свой код, как указано выше, и посмотрите, в какой строке происходит ваша ошибка, и, возможно, это даст вам направление, где искать дальше.

person Scott Chamberlain    schedule 08.03.2014

AsEnumerable просто приводит объект к IEnumerable (из IQeuriable), что означает, что любой оператор LINQ, который вы будете использовать, будет использовать оператор, объявленный для этого интерфейса (IEnumerable).

Это означает, что вместо того, чтобы переводить ваши операторы в SQL и позволять серверу обрабатывать это, вся таблица будет перечисляться (извлекаться из БД), а затем обрабатываться в памяти.

Как упомянул @Scott Chamberlain, то, что я ответил, не имеет отношения к вашему коду, поскольку он использует DataTable, а не IQueriable. AsEnumerable просто создает перечисляемую оболочку для DataTable, которая извлекает каждую строку за раз и позволяет вам использовать LINQ на DataTable. Это не имеет ничего общего с исключением.

Другое дело, что вызов ToList приводит к принудительному выполнению запроса, поэтому выполнение не откладывается.

Чтобы ответить на ваш вопрос об исключении, было бы полезно, если бы вы предоставили код, в котором вы добавляете параметры к запросу.

person Shlomi Borovitz    schedule 08.03.2014
comment
У него нет IQueryable, у него есть DataTable, AsEnumerable(), по которому он звонит, это эта версия не эта версия - person Scott Chamberlain; 08.03.2014