none
LINQ to Entitiesでの誤動作 RRS feed

  • 質問

  • LINQ to EntitiesでSQLデータベースへのアクセスを行っているのですが、

    データベースの操作がうまくいかず悩んでいます。

    たとえば、下記のデータベースがあったとします。

    id(主KEY) name price
    1 りんご        300
    2 バナナ        200
    3 梨          400

    問題点:

    下記のコードでりんごのデータベースを削除すると、データベースの内容がバナナ、梨も含んですべて抹消されてしまいます。

                using (TEST_Entities entry = new TEST_Entities())
                {
                    var query = (from data in entry.Table
                                 where data.Id == 1
                                 select data).Single();

                    entry.Table.Remove(query);
                    entry.SaveChanges();
                }

    しかし、上記のコードを下記のように変えると正常にりんごだけ削除されます。

                using (TEST_Entities entry = new TEST_Entities())
                {
                    var query = (from data in entry.Table
                                 where data.Id == 1
                                 select data).ToArray()[0];

                    entry.Table.Remove(query);
                    entry.SaveChanges();
                }

    実は先日、Single()を使ったことで数万件のデータが一気に吹き飛ばされる事態になりました。(バックアップにて復元しましたが)

    検証の結果、ToArray()を使うと正常動作しましたが、Single()のメソッド自体にバグがあるのでしょうか?

    使用環境は下記のとおりです。

    ・Windows 7 64bit(Window 10でも同じ症状が発生します)

    ・Visual Studio 2017

    ・.NET Framework 4.6.1

    ・Entity Framework 6.2.0

    それから、サーバ側はMicrosoft SQL Server 2014です。

    2018年11月12日 0:39

すべての返信

  • 前のスレッド(URL 下記)が放置状態です。

    LINQ to Entitiesのモデル作成時にデータ消失
    https://social.msdn.microsoft.com/Forums/ja-JP/40388996-cec1-4259-a13d-c90b57c1fa9e/linq-to?forum=csharpgeneralja

    レスに対するフィードバックを返してください。例え「内容が意味不明」とか「役に立たない」とかのフィードバックでも無言で放置よりは∞倍マシだと思うのですが。

    そして、クローズするまでフォローしてください。

    2018年11月12日 1:12
  • ぱっと見ではSingle()の場合でもコードに問題があるようには見受けられないのですが、実際に何が起こっているのかを確認するためにも、Database.Logを使って実際に発行されるSQLを確認することをお勧めします。

    Database.Log プロパティ

    2018年11月12日 1:32
  • 申し訳ありません。

    前回の投稿にレスを行いました。いったんクローズいたします。

    2018年11月12日 1:50
  • > 下記のコードでりんごのデータベースを削除すると、データベースの内容がバナナ、梨も含んですべて抹消されてしまいます。

    Table に他のテーブルとの FK 制約が張られていて連鎖削除が有効になっているというようなことがなければ、そのコードで「すべて抹消」ということはないはずです。

    SaveChanges 直前で各エンティティの State を調べてみてはいかがですか? そのコードを見る限り、ID が 1 のエンティティの State のみが Deleted で、他は Unchanged になるはずなのですが。以下のようにして調べられます。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Data.Entity;
    
    namespace ConsoleAppJoinByLinq
    {
        class Program
        {
            static void Main(string[] args)
            {
                NORTHWINDEntities context = new NORTHWINDEntities();
    
                var query = (from data in context.Employees
                             where data.EmployeeID == 1
                             select data).Single();
    
                context.Employees.Remove(query);
    
                foreach (Employees e in context.Employees)
                {
                    EntityState state = context.Entry(e).State;
                    Console.WriteLine($"EmployeeID: {e.EmployeeID}, EntytySate: {state}");
                }
    
                // 結果は:
                // EmployeeID: 1, EntytySate: Deleted
                // EmployeeID: 2, EntytySate: Unchanged
                // EmployeeID: 3, EntytySate: Unchanged
                // EmployeeID: 4, EntytySate: Unchanged
                // EmployeeID: 5, EntytySate: Unchanged
                // EmployeeID: 6, EntytySate: Unchanged
                // EmployeeID: 7, EntytySate: Unchanged
                // EmployeeID: 8, EntytySate: Unchanged
                // EmployeeID: 9, EntytySate: Unchanged
            }
        }
    }

    質問にアップされたコード以外のところで何らかの操作をしていて、結果全部 Deleted になっているとすると「すべて抹消」ということになると思いますが・・・


    • 編集済み SurferOnWww 2018年11月12日 6:26 訂正
    2018年11月12日 6:26
  • ありがとうございます。

    さらに検証したところ、SQL上で主キーが正常に設定されていないために起こっているようでした。

    再度IDに主キーを設定しなおしたら、問題なく作動し始めました。

    ご迷惑をおかけいたしました。

    2018年11月15日 4:01
  • Takashi Shinohara さんと私が回答・レスを書いてますが、それらに対するフィードバックはいただけないのですか?

    上の私のレスで書きましたが、フィードバックを返してください。例え「内容が意味不明」とか「役に立たない」とかのフィードバックでも無言で放置よりは∞倍マシだと思うのですが。

    > SQL上で主キーが正常に設定されていないために起こっているようでした。

    主キーを持たないテーブルから EDM を作成しようとすると、デザイナが NULL 不許可の列を主キーとして推定して EDM を生成しますが、その場合でも以下のようなメッセージが出ると思います。質問者さんの場合はどうだったのでしょう?

    「テーブル/ビュー 'xxxxx' には主キーが定義されていません。主キーは推論され、定義は読み取り専用のテーブル/ビューとして作成されました。」

    (注)全列が NULL 許可の場合、デザイナは主キーを推定できず、有効な EDM を生成できないので、以下のエラーメッセージが出ると思います。

    「テーブル/ビュー 'xxxxx' に主キーが定義されておらず、有効な主キーを推論できませんでした。このテーブル/ビューは除外されました。エンティティを使用するには、スキーマを確認し、正しいキーを追加して、コメントを解除する必要があります。」
    2018年11月15日 5:37