質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

3580閲覧

C# のEntity frameworkで、元のデータを編集して新規のデータを追加しようとするとPrimary Keyのカラムを変更出来ない

micchi

総合スコア36

Entity Framework

Entity Frameworkは、.NET Framework 3.5より追加されたデータアクセス技術。正式名称は「ADO.NET Entity Framework」です。データベースエンジンに依存しておらず、データプロバイダの変更のみで様々なデータベースに対応できます。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2021/08/24 12:13

Visual Studio 2015のC#でEntity Frameworkで出来たアプリで
データの編集をしているのですが
新しいレコードを作成し、レコードに追加しようとするとプライマリーキーを変更するとエラーになってしまいます
わざわざPKがかぶらないようにしたのですが・・・
元のデータを編集して、一部のデータを変えただけで新規のデータを作りたいのですが
こういった場合に新規データを作りたい場合はどうしたらいいのでしょうか

カラム数が多いのですが一部を書き換えて増殖したいだけなのです

using (var context = TBL_DBAccess.GetEntities()) var item = context.TABLENAME.Single(n => n.ID == id); //編集元のデータを持ってくる item.ID= 100; //ここがPK item.col1= 200; item.col2= "test"; context.TABLENEME.Add(item); //新しいレコードを追加★★★->プライマリーキーの変更は出来ませんというエラー //テーブルの書換 context.SaveChanges(); }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/08/24 12:48 編集

DB は何ですか? 対象のテーブルの構造は? ID は IDENTITY とかですか? 「元のデータを編集して新規のデータを追加」というのがそもそも解せないです。やってることは新規データの追加ではなく既存のデータの編集にみえます。であれば普通はそういうこと(主キーの変更)はしないはず。
退会済みユーザー

退会済みユーザー

2021/08/26 02:06

質問者さんの回答への 2021/08/26 10:41 の私のコメントで「後で最初から最後まで Entity Framework を使った案を回答欄に書いておきます。」と書いた件、先ほど回答しておきましたので見てください。
guest

回答3

0

質問者さんの回答への 2021/08/26 10:41 の私のコメントで「後で最初から最後まで Entity Framework を使った案を回答欄に書いておきます。」と書いた件です。

もともとの質問は、タイトルにもあるように「C# のEntity frameworkで」だったはずで、質問者さんの回答のようにするのは、ご自分でも言っているように「無理やりですが・・」だと思います。

質問者さんのコードでなぜエラーになるかと言うと、コンテキストがエンティティを追跡しているからです。

念のため、自分の環境で、以下のような SQL Server のデータベースを使って、同様なことを試してみました。(Id は IDENTITY ではありません)

イメージ説明

質問者さんのコードと同様なことをすると、コンテキスト context がエンティティ table を追跡しているため、質問者さんの場合と同じエラーになります。

イメージ説明

なので、追跡されないようにするというのが解決策の一つになります。それには AsNoTracking メソッドが利用できます。詳しくは以下の記事を見てください。

追跡なしのクエリ
https://docs.microsoft.com/ja-jp/ef/ef6/querying/no-tracking

AsNoTracking メソッドを使って上のコードを書き直すとエラー無く実行されます。

イメージ説明

結果も以下の通り DB に反映されます。

イメージ説明

お試しください。

投稿2021/08/26 02:02

編集2021/08/26 07:59
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

掲示したコードは新規データの追加ではなく、既存データの変更をしています。

データベースの仕組み上、主キーの更新はリンクされている全てのテーブルも更新する必要があり推奨されません。ですから、Entity Framework においてもそのような操作は許可されずエラーが出ているのでしょう。

元のデータを編集して、一部のデータを変えただけで新規のデータを作りたい

まずは コンテキストとエンティティ クラスを使用してデータを追加、変更、および削除する方法 を参照してください。"データの追加" にて新たなエンティティのインスタンスを作成している部分が重要です。

つまり、データの複製をするには、既存のエンティティから新しくインスタンスを作成する必要があります。

C#

1using (var context = new BloggingContext()) 2{ 3 var original = context.Blogs.First(); 4 var clone = new Blog { Url = source.Url }; 5 context.Blogs.Add(clone); 6 context.SaveChanges(); 7}

注意すべき点として主キーを自動採番していない場合は開発者が主キーを重複させないよう実装する必要があります。

投稿2021/08/24 21:41

編集2021/08/25 09:14
BluOxy

総合スコア2663

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

micchi

2021/08/25 09:07

Entity Frameworkで自動的作成したクラスを var clone = new XXX{ itemorg }; としてみたところ、「IEnumerableを実装していないためXXXはコレクション初期化子で初期化することは出来ません」 というエラーになってしまい、新規にデータ作成は出来ないようでした 別の方法で無理やり解決したのでそちらをこれから回答として作成します
BluOxy

2021/08/25 09:25 編集

すみません。書き方を間違えていたので追記しました。 EFで生のSQLを書いたらEFを使用する意味が薄くなりますし、使い方次第ではセキュリティリスクにもなります。 ですから、公式のドキュメントに記載されているような方法で解決できるなら無理に解決するよりそちらを選択した方が不幸を招かないと思います。
micchi

2021/08/25 09:30

重ね重ねありがとうございます。 カラムが大量にあるのと元のレコードのデータが必要なので、元のデータをなんとかしてコピーしないと行けないのと すでに存在するテーブルなのでPKを自動採番にするとかできないです deepcloneでも実装しようかと思ったのですが、それもVSが自動コーディングで作成したクラスなのでなんともならないので(どちらにしろ大量にメンバ変数ごとにコピーするなんてコーディングはしたくないので・・・)
guest

0

自己解決

無理やりですが自己回答です・・
こちらのページに記載されていた
SQL文で元のデータを増殖させて

string strSql ="select * into #wktbl from tbl1"+ Environment.NewLine; strSql += "alter table #wktbl drop column id"+ Environment.NewLine; strSql += "insert into tbl1 select 1 as id ,* from #wktbl"+ Environment.NewLine; context.Database.ExecuteSqlCommand(strSql);//★SQL分を無理やり実行

そこから

var tmp = context.tabl.Single(n => n.ID == 999);

として引っ張り出して、キー以外の部分を変更して保存としたら上手く行きました

海外だとストアド作ってをキックするとかしてますが、そこまですることも無いかと思いこちらの方法を使いました

投稿2021/08/25 09:12

micchi

総合スコア36

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/08/25 23:05

もともとの質問はタイトルにもあるように「C# のEntity frameworkで」だったはずです。上のようにするのは話が違うと思います。
退会済みユーザー

退会済みユーザー

2021/08/26 01:41

後で最初から最後まで Entity Framework を使った案を回答欄に書いておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問