80

Entity Framework - 「SaveChanges」を呼び出す前に、トランザクション内で新しく作成された ID (ID) を取得する方法はありますか?

2 回目の挿入には ID が必要ですが、常に 0 として返されます...

        ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;

        objectContext.Connection.Open();

        using (var transaction = objectContext.Connection.BeginTransaction())
        {
            foreach (tblTest entity in saveItems)
            {
                this.context.Entry(entity).State = System.Data.EntityState.Added;
                this.context.Set<tblTest>().Add(entity);

                int testId = entity.TestID;

                .... Add another item using testId
            }

            try
            {
                context.SaveChanges();
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                objectContext.Connection.Close();
                throw ex;
            }
        }

        objectContext.Connection.Close();
4

6 に答える 6

66

ID は、行がテーブルに挿入された後にデータベースによって生成されます。行が挿入される前に、その値がどうなるかをデータベースに尋ねることはできません。

これには 2 つの方法があります。最も簡単なのは を呼び出すことSaveChangesです。トランザクション内にいるため、ID を取得した後に問題が発生した場合にロールバックできます。

2 番目の方法は、データベースの組み込みIDENTITYフィールドを使用せずに、自分で実装することです。これは、大量の一括挿入操作がある場合に非常に便利ですが、代償が伴います。実装するのは簡単ではありません。

編集: SQL Server 2012 には、IDENTITY 列の代わりに使用できる組み込みの SEQUENCE 型があり、自分で実装する必要はありません。

于 2013-07-08T09:50:21.327 に答える
48

他の人がすでに指摘しているように、saveChanges()呼び出される前にデータベースによって生成された増分値にアクセスすることはできませんidEF Core によって割り当てられた一時 IDを利用することもできます。

使用されているデータベース プロバイダーに応じて、EF によってクライアント側で、またはデータベース内で値が生成される場合があります。値がデータベースによって生成された場合、エンティティをコンテキストに追加すると、EF によって一時的な値が割り当てられることがあります。この一時的な値は、SaveChanges() 中にデータベースで生成された値に置き換えられます。

これがどのように機能するかを示す例を次に示します。が呼び出される前に割り当てる必要があるプロパティを介してMyEntity参照されているとします。MyOtherEntityMyEntityIdsaveChanges

var x = new MyEntity();        // x.Id = 0
dbContext.Add(x);              // x.Id = -2147482624 <-- EF Core generated id
var y = new MyOtherEntity();   // y.Id = 0
dbContext.Add(y);              // y.Id = -2147482623 <-- EF Core generated id
y.MyEntityId = x.Id;           // y.MyEntityId = -2147482624
dbContext.SaveChangesAsync();
Debug.WriteLine(x.Id);         // 1261 <- EF Core replaced temp id with "real" id
Debug.WriteLine(y.MyEntityId); // 1261 <- reference also adjusted by EF Core

上記は、ナビゲーション プロパティを介して参照を割り当てるy.MyEntity = x場合にも機能します。y.MyEntityId = x.Id

于 2019-01-18T18:45:42.520 に答える
6

@zmbq は正しいです。変更の保存を呼び出した後にのみ ID を取得できます。

私の提案は、データベースの生成された ID に頼るべきではないということです。データベースは、不可欠で変更不可能な部分ではなく、アプリケーションの詳細のみであるべきです。

その問題を回避できない場合は、一意であるため、GUID を識別子として使用してください。MSSQL は GUID をネイティブの列型としてサポートしており、高速です (ただし、INT より高速ではありません)。

乾杯

于 2013-07-08T09:55:13.490 に答える