ここでは、LINQ を実装するときに発生する可能性のある一般的な問題の対処法について説明します。
その他の問題については、「トラブルシューティング (LINQ to SQL)」を参照してください。
Q. データベースに接続できません。
A. 接続文字列が正しいこと、および SQL Server のインスタンスが実行中であることを確認してください。 また、LINQ to SQL では、名前付きパイプ プロトコルを有効にする必要があります。 詳細については、「チュートリアルによる学習 (LINQ to SQL)」を参照してください。
Q. データベース内のデータを変更しましたが、アプリケーションを再実行すると、変更が元に戻っています。
A. 変更結果をデータベースに保存するために、必ず SubmitChanges を呼び出してください。
Q. データベース接続が開いている時間は、どれほどですか。
A. 通常、接続は、クエリ結果を処理するまでは開いた状態を保ちます。 すべての結果を処理するのに時間がかかる可能性がある場合、結果をキャッシュに入れることが可能であれば、クエリに対して ToList
接続が厳密にどのように使用されるかは、以下に応じて異なります。
接続オブジェクトを使って DataContext が作成されている場合は、接続状態。
接続文字列の設定 (たとえば、複数のアクティブな結果セット (MARS) の有効化)。 詳細については、「複数のアクティブな結果セット (MARS)」を参照してください。
Q. データベースに対してあらかじめクエリを実行せずに、テーブル データを更新できますか?
A. LINQ to SQL にはセットベースの更新コマンドはありませんが、次のいずれかの技法を使用すると、あらかじめクエリを実行せずに更新できます。
ExecuteCommand を使って SQL コードを送信する。
オブジェクトの新しいインスタンスを作成し、更新に関連したすべての現在値 (フィールド) を初期化する。 その後、Attach を使ってオブジェクトを DataContext に関連付け、更新対象のフィールドを変更します。
Q. 予期しない結果がクエリから返されます。 どうなっているのか調べる方法はありますか。
A. LINQ to SQL には、生成された SQL コードを調べるためのツールがいくつか用意されています。 このうち、最も重要なものは Log です。 詳細については、「デバッグのサポート (LINQ to SQL)」を参照してください。
Q. 戻り値が MAX() によって計算されるストアド プロシージャがあります。 このストアド プロシージャを O/R デザイナー サーフェイスにドラッグすると、戻り値が正しくありません。
A. 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
詳細については、「ストアド プロシージャによる操作のカスタマイズ (LINQ to SQL)」を参照してください。
Q. シリアル化を試みると、「アセンブリ ... の型 'System.Data.Linq.ChangeTracker+StandardChangeTracker' はシリアル化可能として設定されていません。」というエラーが発生します。
A. LINQ to SQL のコード生成では、DataContractSerializer のシリアル化がサポートされます。 XmlSerializer および BinaryFormatter はサポートされません。 詳細については、「シリアル化 (LINQ to SQL)」を参照してください。
Q. あるデータベース テーブルに DateCreated という列があり、その既定値は SQL Getdate() です。 LINQ to SQL を使用して新しいレコードを挿入しようとすると、値が NULL に設定されます。 データベースの既定値が設定されるようにするには、どうしたらいいですか。
A. ID 列 (自動インクリメント)、rowguidcol 列 (データベースが生成した GUID)、およびタイムスタンプ列の場合は、LINQ to SQL が、このような状況に自動的に対処します。 それ以外の場合には、手動で IsDbGenerated=true プロパティと AutoSync=Always/OnInsert/OnUpdate プロパティを設定する必要があります。
Q. 最初の読み込みオプションを上書きせずに、追加の読み込みオプションを指定できますか?
A. はい。 次の例のように、最初のオプションは上書きされません。
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);
Q. LINQ to SQL は、SQL 注入攻撃からどのように保護されますか?
A. ユーザー入力の連結により形成される従来の SQL クエリでは、SQL 注入が大きなリスクでした。 LINQ to SQL では、クエリで SqlParameter を使用することにより、そのような注入を防止します。 ユーザー入力はパラメーター値に変換されます。 この手法は、顧客の入力で悪意のあるコマンドが使用されることを防止します。
Q. DBML ファイルからオブジェクト モデルを作成するときに、どうすれば、特定のプロパティから setter を取り除くことができますか?
A. これは高度なシナリオですが、以下の手順に従ってください。
.dbml ファイル内で、IsReadOnly フラグを True に変更することにより、プロパティを変更します。
部分クラスを追加します。 読み取り専用メンバー用のパラメーターを使ってコンストラクターを作成します。
既定の UpdateCheck 値 (Never) がアプリケーションにとって適切な値かどうかを検討します。
注意Visual Studio でオブジェクト リレーショナル デザイナーを使用している場合は、変更内容が上書きされる可能性があります。
Q. System.Data.Linq は、部分的に信頼されているコードが使用できるようにマークされていますか?
A. はい。System.Data.Linq.dll アセンブリは、AllowPartiallyTrustedCallersAttribute 属性でマークされている .NET Framework アセンブリの 1 つです。 このマークがないと、.NET Framework のアセンブリは完全に信頼されたコードによってのみ使用されます。
部分的に信頼される呼び出し元を LINQ to SQL で許可する主なシナリオは、trust 構成が Medium の Web アプリケーションから LINQ to SQL アセンブリにアクセスできるようにする場合です。
Q. エンティティに、複数のテーブルから取得されたデータが含まれています。 どのようにマップできますか?
A. データベース内にビューを作成して、エンティティをそのビューにマップすることができます。 LINQ to SQL は、テーブル用と同じ SQL をビュー用に生成します。
メモ |
|---|
このシナリオでのビューの使用には、制限があります。 この手法は、Table |
Q. DataContext プールに役立つコンストラクトはありますか?
A. DataContext のインスタンスは再使用しないようにしてください。 DataContext はそれぞれ、特定の 1 つの編集/クエリ セッション用の状態 (ID キャッシュを含む) を保持します。 データベースの現在の状態に基づく新しいインスタンスを得るには、新しい DataContext を使用してください。
それでも、基になる ADO.NET 接続プールは使用できます。 詳細については、「SQL Server の接続プール (ADO.NET)」を参照してください。
Q. データベース内の値を格納するために、DataContext の 1 つのインスタンスを使用しました。 しかし、同じデータベースに対する 2 番目の DataContext では、更新された値が反映されません。 2 番目の DataContext インスタンスは、キャッシュされた値を返すようです。
A. この動作は意図されたものです。 LINQ to SQL は、最初のインスタンスと同じインスタンス/値を返し続けます。 更新の際には、オプティミスティック同時実行が使用されます。 元のデータを使ってデータベースの現在の状態を検査し、実際に未変更であることをアサートします。 変更されている場合は競合が発生するため、アプリケーションでそれを解決する必要があります。 1 つのオプションとして、アプリケーションは、元の状態をデータベースの現在の状態にリセットして、更新を再試行できます。 詳細については、「方法 : 変更の競合を管理する (LINQ to SQL)」を参照してください。
また、ObjectTrackingEnabled を false に設定することもできます。この場合、キャッシュと変更追跡が無効になります。 その後は、クエリを実行するたびに最新の値を取得できます。
メモ