Вопросы и ответы

В следующих разделах рассматриваются некоторые распространенные проблемы, которые могут возникнуть при реализации LINQ.

В устранении неполадок рассматриваются дополнительные проблемы.

Не удается подключиться

Не удается соединиться с базой данных.

Убедитесь, что строка подключения правильно и запущен ли экземпляр SQL Server. Обратите внимание также, что LINQ to SQL требует включения протокола именованных каналов. Дополнительные сведения см. в разделе Обучение пошагового руководства.

Потеряны изменения, внесенные в базу данных

В базу данных были внесены изменения, однако при повторном запуске приложения их там не оказалось.

Проверьте, что для сохранения результатов в базе данных был вызван метод SubmitChanges.

Как долго сохраняется открытым соединение с базой данных?

Как долго соединение с базой данных будет оставаться открытым?

Как правило, подключение остается открытым до тех пор, пока не будут использованы результаты запроса. Если планируется выделить время для обработки и кэширования всех результатов, к запросу следует применить ToList. В распространенных сценариях, когда каждый объект обрабатывается только один раз, модель потоковой передачи выше в обоих DataReader случаях и в LINQ to SQL.

Точные сведения об использовании подключения зависят от следующих моментов.

Обновление без выполнения запросов

Можно ли обновить данные таблицы, не отправляя запрос в базу данных?

Хотя у LINQ to SQL нет команд обновления на основе набора, можно использовать любой из следующих методов для обновления без первого запроса:

  • Чтобы отправить код SQL, используйте ExecuteCommand.

  • Создайте новый экземпляр объекта и инициализируйте все текущие значения (поля), влияющие на обновление. Затем прикрепите объект к DataContext с помощью Attach и отредактируйте поле, которое нужно изменить.

Неожиданные результаты запроса

Запрос возвращает непредвиденные результаты. Как узнать, что случилось?

LINQ to SQL предоставляет несколько средств для проверки кода SQL, который он создает. Одним из наиболее важных Log. Дополнительные сведения см. в разделе "Поддержка отладки".

Неожиданные результаты хранимой процедуры

У меня есть хранимая процедура, возвращаемая значением которой вычисляется значение MAX(). При перетаскивании хранимой процедуры в область конструктора O/R возвращаемое значение неправильно.

LINQ to SQL предоставляет два способа возврата созданных базой данных значений путем хранимых процедур:

  • Путем именования выходного результата.

  • Путем явного указания выходного параметра.

Ниже представлен пример неверных выходных данных. Так как LINQ to SQL не может сопоставить результаты, он всегда возвращает значение 0:

create procedure proc2

as

begin

select max(i) from t where name like 'hello'

end

Ниже представлен пример правильных выходных данных с использованием выходного параметра.

create procedure proc2

@result int OUTPUT

as

select @result = MAX(i) from t where name like 'hello'

go

Ниже представлен пример правильных выходных данных с именованием выходного результата.

create procedure proc2

as

begin

select nax(i) AS MaxResult from t where name like 'hello'

end

Дополнительные сведения см. в разделе "Настройка операций с помощью хранимых процедур".

Ошибки сериализации

При попытке сериализации я получаю следующую ошибку: "Тип System.Data.Linq.ChangeTracker+StandardChangeTracker" ... не помечен как сериализуемый".

Создание кода в LINQ to SQL поддерживает DataContractSerializer сериализацию. Оно не поддерживает XmlSerializer или BinaryFormatter. Дополнительные сведения см. в разделе Сериализация.

Несколько DBML-файлов

При работе с несколькими DBML-файлами, использующими общие таблицы, возникает ошибка компилятора.

Задайте свойства пространства имен контекста и пространства имен сущностей из реляционный конструктор объектов в отдельное значение для каждого файла DBML. Это способ исключает конфликты имен/пространств имен.

Предупреждение явного задания значений, созданных базой данных, в Insert или Update

У меня есть таблица базы данных с столбцом DateCreated, который по умолчанию используется для SQL Getdate(). При попытке вставить новую запись с помощью LINQ to SQL значение получает значение NULL. Хотя ожидается заданное по умолчанию значение базы данных.

LINQ to SQL обрабатывает эту ситуацию автоматически для удостоверений (автоматического увеличения) и rowguidcol (GUID, созданных базой данных) и столбцов метки времени. В других случаях следует вручную задать IsDbGeneratedtrueAlways=OnUpdateAutoSync/OnInsert/свойства.

Несколько параметров DataLoadOptions

Можно ли задать дополнительные параметры загрузки, не переопределяя исходные?

Да. Исходные параметры не переопределяются, как показано в следующем примере.

Dim dlo As New DataLoadOptions()
dlo.LoadWith(Of Order)(Function(o As Order) o.Customer)
dlo.LoadWith(Of Order)(Function(o As Order) o.OrderDetails)
DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Order>(o => o.Customer);
dlo.LoadWith<Order>(o => o.OrderDetails);

Ошибки при использовании SQL Compact 3.5

При перетаскивании таблиц из базы данных SQL Server Compact 3.5 возникает ошибка.

Реляционный конструктор объектов не поддерживает SQL Server Compact 3.5, хотя среда выполнения LINQ to SQL выполняется. В этом случае необходимо создать собственные классы сущностей и добавить соответствующие атрибуты.

Ошибки в связях наследования

Я использовал фигуру наследования элементов в реляционный конструктор объектов для подключения двух сущностей, но я получаю ошибки.

Простого создания связи недостаточно. Необходимо предоставить сведения, такие как столбец дискриминатора, значение дискриминатора базового класса и значение дискриминатора производного класса.

Модель поставщика

Доступна ли модель общего поставщика?

Такая модель отсутствует. В настоящее время LINQ to SQL поддерживает только SQL Server и SQL Server Compact 3.5.

Атаки путем внедрения кода SQL

Как LINQ to SQL защищается от атак на внедрение SQL?

Внедрение SQL-кода представляло серьезную угрозу для традиционных SQL-запросов, создаваемых путем объединения данных, вводимых пользователем. LINQ to SQL избегает такой внедрения с помощью SqlParameter запросов. Вводимые данные преобразуются в значения параметров. Этот способ исключает использование вредоносных команд из введенных данных.

Создание флага "Только чтение" в файлах DBML.

Как можно избавиться от некоторых методов задания свойств при создании объектной модели из файла DBM?

Выполните следующие действия.

  1. В файле DBML измените свойство, присвоив флагу IsReadOnly значение True.

  2. Добавьте разделяемый класс. Создайте конструктор с параметрами для членов, доступных только для чтения.

  3. Проверьте значение по умолчанию UpdateCheck (Never), чтобы определить, является ли оно правильным для приложения.

    Внимание

    Если вы используете реляционный конструктор объектов в Visual Studio, изменения могут быть перезаписаны.

APTCA

Помечена ли сборка System.Data.Linq для использования кодом с частичным доверием?

Да, сборка System.Data.Linq.dll входит в число платформа .NET Framework сборок, помеченных атрибутомAllowPartiallyTrustedCallersAttribute. Без этой маркировки сборки в платформа .NET Framework предназначены только для использования полностью доверенным кодом.

Основной сценарий в LINQ to SQL для разрешения частично доверенных вызывающих объектов — разрешить доступ к сборке LINQ to SQL из веб-приложений, где конфигурация доверия — средняя.

Сопоставление данных из нескольких таблиц

Данные в сущность поступают из нескольких таблиц. Как их сопоставить?

В базе данных можно создать представление и сопоставить с ним сущность. LINQ to SQL создает тот же SQL для представлений, что и для таблиц.

Примечание.

В данном сценарии использование представлений имеет ограничения. Способ работает с максимальной безопасностью, если операции, выполняемые в Table<TEntity>, поддерживаются базовым представлением. Операции, которые предполагается использовать, известны только вам. Например, большинство приложений доступны только для чтения, а другое размерное число выполняет Create//UpdateDelete операции только с помощью хранимых процедур в представлениях.

Объединение подключений в пул

Существует ли конструкция, которая может помочь в пуле DataContext?

Не пытайтесь повторно использовать экземпляры DataContext. Каждый DataContext сохраняет состояние (включая кэш идентификации) для одного определенного сеанса редактирования/запроса. Для получения новых экземпляров на основе текущего состояния базы данных используйте новый DataContext.

Вы по-прежнему можете использовать базовые ADO.NET пул соединений. Дополнительные сведения см. в разделе Объединение подключений в пул в SQL Server (ADO.NET).

Не выполняется обновление второго DataContext

Я использовал один экземпляр DataContext для хранения значений в базе данных. Однако второй dataContext в той же базе данных не отражает обновленные значения. Второй экземпляр DataContext, кажется, возвращает кэшированные значения.

Такое поведение предусмотрено программой. LINQ to SQL продолжает возвращать те же экземпляры и значения, которые вы видели в первом экземпляре. При выполнении обновлений используется оптимистическая блокировка. Для проверки текущего состояния базы данных используются исходные данные, которые подтверждают неизменность ее состояния. Если состояние изменилось, возникает конфликт, который должен быть устранен приложением. Одним вариантом является сброс исходного состояния до текущего состояния базы данных и повторная попытка обновления. Дополнительные сведения см. в статье "Управление конфликтами изменений".

Кроме того, ObjectTrackingEnabled можно задать значение «false», которое отключает кэширование и отслеживание изменений. После этого самые последние значения можно будет извлекать при каждом запросе.

Не удается вызвать метод SubmitChanges в режиме "только чтение"

При попытке вызвать SubmitChanges в режиме только для чтения возникает ошибка.

Режим только для чтения отключает для контекста возможность отслеживания изменений.