次のセクションでは、LINQ を実装するときに発生する可能性のある一般的な問題について説明します。
その他の問題については、「 トラブルシューティング」を参照してください。
接続できない
データベースに接続できません。
接続文字列が正しく、SQL Server インスタンスが実行されていることを確認します。 LINQ to SQL では、名前付きパイプ プロトコルを有効にする必要があることにも注意してください。 詳細については、「 チュートリアルによる学習」を参照してください。
データベースの失われた変更
データベース内のデータに変更を加えたが、アプリケーションを再ランすると、変更は存在しなくなった。
結果をデータベースに保存するには、必ず SubmitChanges を呼び出してください。
データベース接続: 開く時間
データベース接続はどのくらいの期間開いたままですか?
通常、接続はクエリ結果を使用するまで開いたままです。 すべての結果の処理に時間がかかることが予想され、結果のキャッシュに反対していない場合は、クエリに ToList を適用します。 各オブジェクトが 1 回だけ処理される一般的なシナリオでは、ストリーミング モデルは DataReader
と LINQ to SQL の両方で優れています。
接続の使用状況の正確な詳細は、次によって異なります。
DataContextが接続オブジェクトで構築されている場合の接続状態。
接続文字列の設定 (たとえば、複数のアクティブな結果セット (MARS) を有効にする)。 詳細については、「 複数のアクティブな結果セット (MARS)」を参照してください。
クエリを実行せずに更新する
最初にデータベースにクエリを実行せずにテーブル データを更新できますか?
LINQ to SQL にはセット ベースの更新コマンドはありませんが、最初にクエリを実行せずに更新するには、次のいずれかの手法を使用できます。
ExecuteCommandを使用して SQL コードを送信します。
オブジェクトの新しいインスタンスを作成し、更新に影響するすべての現在の値 (フィールド) を初期化します。 次に、DataContextを使用してオブジェクトをAttachにアタッチし、変更するフィールドを変更します。
予期しないクエリ結果
クエリが予期しない結果を返しています。 何が発生しているかを調べるにはどうすればよいですか?
LINQ to SQL には、生成される SQL コードを検査するためのツールがいくつか用意されています。 最も重要なものの 1 つは、 Logです。 詳細については、「 デバッグのサポート」を参照してください。
予期しないストアド プロシージャの結果
戻り値が 'MAX()'によって計算されるストアドプロシージャがあります。 ストアド プロシージャを O/R デザイナー画面にドラッグすると、戻り値が正しくありません。
LINQ to SQL には、ストアド プロシージャを使用してデータベースで生成された値を返す 2 つの方法があります。
出力結果に名前を付ける。
出力パラメーターを明示的に指定する。
正しくない出力の例を次に示します。 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
詳細については、「 ストアド プロシージャを使用した操作のカスタマイズ」を参照してください。
シリアル化エラー
シリアル化しようとすると、"Type 'System.Data.Linq.ChangeTracker+StandardChangeTracker' ...はシリアル化可能としてマークされていません。
LINQ to SQL でのコード生成では、 DataContractSerializer シリアル化がサポートされます。 XmlSerializerまたはBinaryFormatterはサポートされていません。 詳細については、「Serialization」 (シリアル化) を参照してください。
複数の DBML ファイル
一部のテーブルを共通に共有する複数の DBML ファイルがある場合、コンパイラ エラーが発生します。
オブジェクト リレーショナル デザイナーの コンテキスト名前空間 プロパティと エンティティ名前空間 プロパティを、DBML ファイルごとに個別の値に設定します。 この方法では、名前と名前空間の競合が解消されます。
挿入または更新時の Database-Generated 値の明示的な設定の回避
SQL 'Getdate()' の既定値である 'DateCreated' 列を持つデータベース テーブルがあります。 LINQ to SQL を使用して新しいレコードを挿入しようとすると、値が 'NULL' に設定されます。 私はそれがデータベースのデフォルトに設定されることを期待するでしょう。
LINQ to SQL は、ID (自動インクリメント) 列と rowguidcol (データベース生成 GUID) 列とタイムスタンプ列に対して、この状況を自動的に処理します。 それ以外の場合は、 IsDbGenerated=true
プロパティと AutoSync=Always/OnInsert/OnUpdate プロパティを手動で設定する必要があります。
複数の DataLoadOptions
最初の読み込みオプションを上書きせずに追加の読み込みオプションを指定できますか?
はい。 次の例のように、1 つ目は上書きされません。
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 ランタイムではサポートされています。 このような場合は、独自のエンティティ クラスを作成し、適切な属性を追加する必要があります。
継承リレーションシップのエラー
オブジェクト リレーショナル デザイナーのツールボックス継承図形を使用して 2 つのエンティティを接続しましたが、エラーが発生します。
リレーションシップを作成するだけでは不十分です。 識別子列、基底クラスの識別子の値、派生クラスの識別子の値などの情報を指定する必要があります。
プロバイダー モデル
パブリック プロバイダー モデルは利用できますか?
パブリック プロバイダー モデルは使用できません。 現時点では、LINQ to SQL では SQL Server と SQL Server Compact 3.5 のみがサポートされています。
SQL-Injection 攻撃
LINQ to SQL は SQL インジェクション攻撃からどのように保護されますか?
SQL インジェクションは、ユーザー入力を連結して形成された従来の SQL クエリにとって重大なリスクでした。 LINQ to SQL では、クエリで SqlParameter を使用することで、このような挿入を回避できます。 ユーザー入力はパラメーター値に変換されます。 この方法により、悪意のあるコマンドが顧客の入力から使用されるのを防ぐことができます。
DBML ファイルの読み取り専用フラグの変更
DBML ファイルからオブジェクト モデルを作成するときに、一部のプロパティからセッターを削除するにはどうすればよいですか?
この高度なシナリオでは、次の手順を実行します。
.dbml ファイルで、 IsReadOnly フラグを
True
に変更して、プロパティを変更します。部分クラスを追加します。 読み取り専用メンバーのパラメーターを持つコンストラクターを作成します。
既定の UpdateCheck 値 (Never) を確認して、それがアプリケーションの正しい値であるかどうかを判断します。
注意事項
Visual Studio でオブジェクト リレーショナル デザイナーを使用している場合は、変更が上書きされる可能性があります。
APTCA
System.Data.Linq は部分的に信頼されたコードで使用できるようにマークされていますか?
はい。System.Data.Linq.dll アセンブリは、 AllowPartiallyTrustedCallersAttribute 属性でマークされた .NET Framework アセンブリの中にあります。 このマーキングがない場合、.NET Framework のアセンブリは、完全に信頼されたコードでのみ使用することを目的としています。
部分的に信頼された呼び出し元を許可する LINQ to SQL の主なシナリオは、 信頼構成が Medium である Web アプリケーションから LINQ to SQL アセンブリにアクセスできるようにすることです。
複数のテーブルからのデータのマッピング
エンティティ内のデータは、複数のテーブルから取得されます。 マップする方法
データベースにビューを作成し、エンティティをビューにマップできます。 LINQ to SQL では、テーブルの場合と同じ SQL がビューに対して生成されます。
注
このシナリオでのビューの使用には制限があります。 この方法は、 Table<TEntity> に対して実行された操作が基になるビューでサポートされている場合に最も安全に機能します。 どの操作が意図されているかは、ユーザーのみが把握できます。 たとえば、ほとんどのアプリケーションは読み取り専用であり、別のサイズの大きさの数値は、ビューに対してストアド プロシージャを使用してのみ Create
/Update
/Delete
操作を実行します。
接続のプール
DataContext プールに役立つコンストラクトはありますか。
DataContextのインスタンスを再利用しないでください。 各 DataContext は、1 つの特定の編集/クエリ セッションの状態 (ID キャッシュを含む) を維持します。 データベースの現在の状態に基づいて新しいインスタンスを取得するには、新しい DataContextを使用します。
基になる ADO.NET 接続プールは引き続き使用できます。 詳しくは、「SQL Server の接続プール (ADO.NET)」をご覧ください。
Second DataContext が更新されない
DataContext の 1 つのインスタンスを使用して、データベースに値を格納しました。 ただし、同じデータベース上の 2 つ目の DataContext には、更新された値は反映されません。 2 番目の DataContext インスタンスは、キャッシュされた値を返すようです。
この動作は設計によるものです。 LINQ to SQL は、最初のインスタンスで見たのと同じインスタンス/値を引き続き返します。 更新を行うときは、オプティミスティック コンカレンシーを使用します。 元のデータは、現在のデータベースの状態をチェックして、実際には変更されていないことをアサートするために使用されます。 変更された場合、競合が発生し、アプリケーションで解決する必要があります。 アプリケーションの 1 つのオプションは、元の状態を現在のデータベース状態にリセットし、更新を再試行することです。 詳細については、「 方法: 変更の競合を管理する」を参照してください。
ObjectTrackingEnabledを false に設定して、キャッシュと変更の追跡をオフにすることもできます。 その後、クエリを実行するたびに最新の値を取得できます。
読み取り専用モードで SubmitChanges を呼び出すことはできません
読み取り専用モードで SubmitChanges を呼び出そうとすると、エラーが発生します。
読み取り専用モードでは、コンテキストの変更を追跡する機能がオフになります。