#c# #linq #linq-to-sql
Вопрос:
У меня есть столик, мы позвоним Users
. В этой таблице есть один первичный ключ, определенный в SQL Server, — автоинкремент int ID
.
Иногда мои запросы LINQ к этой таблице завершаются "Index was outside the range"
ошибкой — даже самые простые запросы. Сам запрос не использует никаких индексаторов.
Например:
User = Users.Take(1);
или
IEnumerable<Users> = Users.ToList();
Оба запроса выдали одну и ту же ошибку. Используя визуализатор отладчика, чтобы просмотреть сгенерированный запрос — я копирую и вставляю запрос в SQL, и он отлично работает. Я также нажимаю «выполнить» на визуализаторе, и он отлично работает. Но выполнение кода само по себе вызывает эту ошибку. Я не реализую ни один из частичных методов в классе, поэтому там ничего не происходит. Если я перезапущу свой отладчик, проблема исчезнет, только чтобы через несколько часов снова случайно поднять голову. Что еще более важно, я вижу эту ошибку в своих журналах ошибок из приложения, запущенного в рабочей среде.
Я использую тонну LINQ в своем приложении против дюжины или около того различных объектов в своей базе данных, но я вижу эту проблему только в запросах, связанных с конкретным объектом в моей таблице. Некоторые пользователи Google предположили, что эта проблема может быть связана с неправильным отношением, указанным между моей моделью и другим объектом, но у меня нет никаких отношений с этим объектом. Кажется, что он работает в 95% случаев, просто остальные 5% терпят неудачу.
Я полностью удалил объект из конструктора и повторно добавил его из «обновленного» браузера сервера, и это не решило проблему.
Есть идеи, что здесь происходит?
Вот полное сообщение об ошибке и трассировка стека:
Индекс был вне зоны досягаемости. Должно быть неотрицательным и меньше размера коллекции. Имя параметра: индекс в System.Data.Linq.SqlClient.SqlProvider.Выполните(запрос выражения, запрос QueryInfo, фабрика IObjectReaderFactory, родительские запросы объекта [], пользовательские запросы объекта [], подзапросы ICompiledSubQuery [], Последний результат объекта) в System.Data.Linq.SqlClient.SqlProvider.Выполните все(запрос выражения, QueryInfo[] QUERYINFO, фабрика IObjectReaderFactory, документы пользователя объекта [], подзапросы ICompiledSubQuery []) в Системе.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Поставщик.IProvider.Выполните(запрос выражения) в System.Data.Linq.Таблица
1.System.Linq.IQueryProvider.Execute[TResult](Expression
1 источник, выражение`1 предикат) в MyProject.FindUserByType(Идентификатор типа строки)
expression) at
System.Linq.Queryable.FirstOrDefault[TSource](IQueryable
ИЗМЕНИТЬ: Как и было запрошено, ниже приведена копия схемы таблицы.
CREATE TABLE [dbo].[Container](
[ID] [int] IDENTITY(1,1) NOT NULL,
[MarketCode] [varchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Description] [varchar](max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[Capacity] [int] NOT NULL,
[Volume] [float] NOT NULL
CONSTRAINT [PK_Container] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ИЗМЕНИТЬ: Отображается трассировка стека FirstOrDefault
, но я повторил ошибку, используя оба Take()
и ToList()
. Трассировка стека идентична между всеми ними, просто взаимозаменяема FirstOrDefault/Take/ToList
. Перемещение вниз по стеку SqlProvider.Execute
на самом деле идентично.
Комментарии:
1. Понятия не имею, что происходит, но увлекательно! Если все остальное не удастся, вы можете попробовать Общий список проектов Linq: forums.microsoft.com/MSDN/…
2. Это могло бы помочь, если бы мы могли увидеть определение таблицы.
3. ( mssql -> Базы данных ->> the_db ->>> Таблицы — > > > > the_bad_table ->>>>> щелкните правой кнопкой мыши — > > > > > > > Таблица сценариев как — > > > > > > > > > Создать Для)
4. Stacktrace показывает FirstOrDefault, но примеры кода не показывают этот метод. Пожалуйста, покажите код с помощью FirstOrDefault или подтвердите, что он не вызывается.
5. Пожалуйста, вставьте также DBML для этой таблицы (тип сущности)… например….
Ответ №1:
Это почти наверняка не будет основной причиной для всех, но я столкнулся с точно таким же исключением в своем проекте — и обнаружил, что основной причиной было то, что исключение создавалось во время создания класса сущностей. Как ни странно, истинное исключение «потеряно» и вместо этого проявляется как исключение ArgumentOutOfRange, возникающее в итераторе оператора Linq, который извлекает объект/ы.
Если вы получаете эту ошибку и ввели в свои POCOs методы onCreated или OnLoaded, попробуйте пройти через эти методы.
Комментарии:
1. Действительно, это еще один тип исключения, скрытый этим «вне зоны действия». В моем случае у меня была та же проблема, и она заключалась в том, что объект, который я хотел изменить, находился в недопустимом контексте.
Ответ №2:
Я бы сказал, что у вас где-то есть несоответствие модели — > базе данных. Когда я впадаю в такое же отчаяние, как и ты, в подобных ситуациях, я обычно загораюсь VS.NET, создайте новое консольное приложение, перестройте раздел DBML, который ссылается на объект, представляющий интерес в этом запросе, и запустите его повторно. Вы можете обнаружить, что в такой изоляции запрос работает. Вы настраивали какие-либо из своих определений сущностей, заполняя частичные методы, особенно те, которые срабатывают при создании?
Ответ №3:
Исключение возникает в системной библиотеке, и ваша история заставляет меня думать, что проблема не в вашем коде. Изменилась ли схема в последнее время? Правильно ли ваше отображение?
Комментарии:
1. Схема в последнее время не изменилась, хотя у меня уже довольно давно были проблемы. Я удалил таблицу виновников и повторно добавил ее через браузер сервера, но безрезультатно.
Ответ №4:
Эта проблема возникает из-за того, что объект linq и поля базы данных этой таблицы не идентичны.
Ответ №5:
У меня тоже была эта проблема, и я ее решил.
Теперь я понимаю, что ошибка заключалась в неправильном использовании контекста данных Linq, но, возможно, мой опыт все еще может помочь другим понять, почему они получают эту ошибку.
Контекст данных Linq не предназначен для одновременного запуска. Поэтому создание нескольких задач, выполняемых асинхронно, не является идеальным решением. Проверьте следующий пример кода, чтобы понять проблему:
using(var ctx = new LinqDataContext())
{
List<Task> tasks = new List<Task>();
for(int i=0;i<1000;i )
{
var task = Task.Run(() => {
var customer = ctx.Customers.SingleOrDefault(o => o.Id == i);
customer.DoSomething();
}
tasks.Add(task);
}
Task.WaitAll(tasks);
}
В моем сценарии я передавал контекст данных в качестве параметра в более длинном стеке вызовов и по пути вызывал асинхронные методы. Так что это было не так очевидно, как в приведенном выше примере. Но, может быть, это все равно может помочь кому-то другому: -)