2017-11-29 10 views
0

SQLiteとEntity Framework 6(EF6)でON DELETE CASCADEを使用できません。私が行方不明のものはありますか?SQLiteとEntity Framework 6でON DELETE CASCADEを使用する方法

Visual Studio 2015でC#でWindowsフォームアプリケーションを作成しました。アプリケーションでEF6とSQLiteがうまく連携していたため、データを挿入して取得できました。しかし、それは物事を削除するには、1つの行/エンティティを削除するうまく動作しますが、カスケードはまったく動作しません。 SQLiteのDBブラウザでは、まったく同じ行が削除され、カスケードが機能しました。

これはノードを表し、私のテーブルです:

CREATE TABLE `Nodes` (
    `NodeId` INTEGER, 
    `ParentId` INTEGER, 
    `Label` TEXT, 
    PRIMARY KEY(`NodeId`), 
    FOREIGN KEY(`ParentId`) REFERENCES `Nodes`(`NodeId`) ON DELETE CASCADE 
); 

そして、これは私が(カスケードですべての子ノードを削除することになって)「ルート」ノードを削除しています方法です:

var noParentItems = entities.Nodes.Where(n => n.ParentId == null); 
foreach (var root in noParentItems) 
{ 
    //entities.Entry(root).State = EntityState.Deleted; 
    entities.Nodes.Remove(root); 
} 
entities.SaveChanges(); 

注: 「root」を削除するコメント付きバージョンも試しました。 ここでは、すべてのルートノードをキャッチするためにループしていることがわかりますが、これは重要ではありません。

私はEF6のデータベースファーストアプローチを使用しています。これを修正するために、生成されたファイルを変更したくないことに注意してください。

また、これらのソリューションは私のために動作しませんでした:

必要な場合は、追加情報をお気軽にお尋ねください。

ありがとうございました。

+0

https://stackoverflow.com/a/34038321/2946329 –

+0

またはhttps://stackoverflow.com/a/37459049/2946329 –

+0

よく、私は生成されたファイルを変更したくないし、OnModelCreating()生成されたファイルで上書きされます。回避策はありますか? – Sheep

答えて

0

ありがとう、私はこの問題を解決する方法を見つけました。

まず私はこの答えを見て:

Entity Frameworkのは、実際にADO.NETをラップ そのものであるADO.NETデータプロバイダです:重要な部分は、この引用である Cascade on delete not cascading with EF

データプロバイダ(SQLite、具体的には)。 通常、エンティティフレームワークはデータベース接続が必要なときはいつでも、データベース接続 を開きます。これらの自動的に開いた接続は、Entity Frameworkが終了すると自動的に閉じられる です。 この既定の動作は、ADOのためにSQL Serverで正常に動作します。NET プロバイダーの接続プーリングしかし、 SQLite接続では、さまざまな "プロパティ"が存在するため、SQLiteとうまく動作しません。 1つの例は "PRAGMA foreign_keys = ON"で、 外部キーはそのSQLiteデータベース接続にのみ適用されます。エンティティ フレームワークが自由に接続を開いて閉じた場合、SQLite などのPRAGMAは失われます。

したがって、指示を入れる場所がある場合は、接続文字列内にしかありません。

その結果、私はこれを追加しました:

foreign keys=True 

今では正常に動作します!

0

質問にはAsNoTrackingが使用されていませんが、私は知っていますが、このように試すこともできます。

foreach (var root in noParentItems) 
{ 
    entities.Nodes.Attach(root); 
    entities.Entry(root).State = EntityState.Deleted; 
} 

などです。

foreach (var root in noParentItems) 
{ 
    var newRoot = new Node{ NodeId = root.NodeId }; 
    entities.Nodes.Attach(newRoot); 
    entities.Entry(newRoot).State = EntityState.Deleted; 
} 
+0

あなたの答えをありがとう。最初のバージョンは動作しませんでした。 var newRoot = new Nodes {NodeId = root.NodeId}を持つバージョン。同じ主キーを持つ要素を作成するため、例外が発生している可能性があります。 "同じキーを持つオブジェクトが既にObjectStateManagerに存在し、ObjectStateManagerは同じキーを持つ複数のオブジェクトを追跡できません。"というメッセージがあります。 – Sheep

+0

Ohh私の間違い。 2番目の例では、クエリにAsNoTracking()を追加してもう一度やり直しますか? – lucky

+0

正直言って、以前はAsNoTracking()について聞いていませんでした。私はそれをどのように使うべきですか? – Sheep

関連する問題