Asp.netのEntity Frameworkに問題があります。データベースにオブジェクトを追加するたびにId値を取得したいです。これどうやってするの?
とても簡単です。 DBで生成されたID(MS SQLのIDENTITY
など)を使用している場合は、関連するObjectSet
のエンティティをSaveChanges
およびObjectContext
に追加するだけで済みます。 Id
は自動的に埋められます。
using (var context = new MyContext())
{
context.MyEntities.AddObject(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Yes it's here
}
自動生成されたINSERT
が使用されている場合、デフォルトでエンティティフレームワークはId
の後にSELECT SCOPE_IDENTITY()
を付けます。
Ladislav Mrnkaの答え Entity Frameworkの使用時にIDを正常に取得するために使用していましたが、使用しなかったため(必要でない場所で使用したため)ここに掲載しています。ここでの調査結果インケースでは、人々は私が抱えていた問題を「解決」しようとしています。
Customerと外部キーの関係があるOrderオブジェクトを考えます。新しい顧客と新しい注文を同時に追加したとき、私はこのようなことをしていました。
var customer = new Customer(); //no Id yet;
var order = new Order(); //requires Customer.Id to link it to customer;
context.Customers.Add(customer);
context.SaveChanges();//this generates the Id for customer
order.CustomerId = customer.Id;//finally I can set the Id
ただし、私の場合はcustomer.Idとorder.CustomerIdの間に外部キーの関係があるため、これは必要ありませんでした。
私がしなければならなかったのはこれだけでした。
var customer = new Customer(); //no Id yet;
var order = new Order{Customer = customer};
context.SaveChanges();//adds customer.Id to customer and the correct CustomerId to order
変更を保存すると、顧客用に生成されたIDも注文に追加されます。追加の手順は必要ありません
これは元の質問には答えないことを承知していますが、EFに慣れていない開発者が必要ではないかもしれないものに対してトップ投票の答えを使いすぎないようにするのに役立つかもしれないと思いました。
変更を保存した後にエンティティをリロードする必要があります。 EFでは追跡できないデータベーストリガーによって変更されているからです。 SO DBからエンティティを再度リロードする必要があります。
db.Entry(MyNewObject).GetDatabaseValues();
それから
int id = myNewObject.Id;
以下の質問で@jayanthaの回答を見てください。
defaultValueを使用するときにEntity Frameworkで挿入されたエンティティのIDを取得する方法
以下の質問で@christianの回答を見ても役に立ちます。
このリンクを参照してください。
http://www.ladislavmrnka.com/2011/03/the-bug-in-storegeneratedpattern-fixed-in-vs-2010-sp1/
StoreGeneratedPatternのプロパティをidentityに設定してから、独自のコードを試す必要があります。
それ以外の場合はこれを使用することもできます。
using (var context = new MyContext())
{
context.MyEntities.AddObject(myNewObject);
context.SaveChanges();
int id = myNewObject.Id; // Your Identity column ID
}
データベースに変更を反映した後、保存しているオブジェクトは正しいId
を持つはずです。
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;
これはうまくいくでしょう。
保存後にのみIDを取得できますが、代わりに新しいGuidを作成して保存前に割り当てることができます。
私はデータベースにデータを挿入する必要があり、同時にエンティティフレームワークを使用してプライマリIDを必要とする状況に出くわしました。解決策:
long id;
IGenericQueryRepository<myentityclass, Entityname> InfoBase = null;
try
{
InfoBase = new GenericQueryRepository<myentityclass, Entityname>();
InfoBase.Add(generalinfo);
InfoBase.Context.SaveChanges();
id = entityclassobj.ID;
return id;
}
すべての答えはそれぞれのシナリオに非常に適しています。異なる点は、Add()がint変数に返したobject(TEntity)から直接int PKを割り当てたことです。
using (Entities entities = new Entities())
{
int employeeId = entities.Employee.Add(new Employee
{
EmployeeName = employeeComplexModel.EmployeeName,
EmployeeCreatedDate = DateTime.Now,
EmployeeUpdatedDate = DateTime.Now,
EmployeeStatus = true
}).EmployeeId;
//...use id for other work
}
そのため、新しいオブジェクト全体を作成するのではなく、必要なものだけを使用できます。
編集@GertArnold:
2つの戦略があります。
データベース生成のID
(int
またはGUID
)を使用する
短所:
保存したエンティティのID
を取得するには、SaveChanges()
を実行する必要があります。
長所:
int
アイデンティティーを使用できます。
クライアント生成のID
- GUIDのみを使用してください。
長所:SaveChanges
操作の縮小。 1回の操作で新しいオブジェクトの大きなグラフを挿入できるようになりました。
短所:
GUID
に対してのみ許可されています
EF 6.xコードを最初に使用するとき
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
データベーステーブルを初期化すると、
(newsequentialid())
テーブルのプロパティ内で、ヘッダーのDefault ValueまたはBindingの下にあり、IDが挿入されたときにIDを設定できます。
問題は、テーブルを作成して
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
後で説明しますが、将来のアップデートデータベースでは(newsequentialid())が追加されることはありません。
正しい方法を修正するには、移行を抹消し、データベースを削除してから再移行します。あるいは、テーブルデザイナーに(newsequentialid())を追加するだけです。