엔티티 프레임워크 - 트랜잭션 내부의 'Save Changes' 앞에서 ID 검색
Entity Framework에서 - 'Save Changes'를 호출하기 전에 트랜잭션 내에서 새로 생성된 ID(ID)를 검색할 수 있는 방법이 있습니까?
두 번째 삽입을 위해 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();
테이블에 행을 삽입한 후 데이터베이스에 의해 ID가 생성됩니다.행을 삽입하기 전에 데이터베이스에 값을 물어볼 수 없습니다.
두 가지 방법이 있습니다. 가장 쉬운 방법은 전화를 거는 것입니다.SaveChanges
거래 중이므로 아이디를 발급받은 후 문제가 발생할 경우 롤백할 수 있습니다.
된 데이터베이스를 하지 않는 입니다.IDENTITY
필드를 사용할 수 있습니다.대량 삽입 작업이 많은 경우 매우 유용할 수 있지만, 구현하는 것은 사소한 일이 아닙니다.
편집: SQL Server 2012에는 IDENTITY 열 대신 사용할 수 있는 SEQUENCE 유형이 내장되어 있으므로 직접 구현할 필요가 없습니다.
했듯이, 당신은 할 수 .saveChanges()
호출되었습니다 – 그러나, 당신이 오직 관심이 있는 경우.id
다른 엔티티(예: 동일한 트랜잭션)에 연결하기 위한 수단으로 EF Core에서 할당한 임시 ID를 사용할 수도 있습니다.
사용 중인 데이터베이스 공급자에 따라 EF 또는 데이터베이스에서 값이 클라이언트 쪽으로 생성될 수 있습니다.값이 데이터베이스에서 생성된 경우 EF는 컨텍스트에 엔티티를 추가할 때 임시 값을 할당할 수 있습니다. 그러면 변경 내용 저장() 중에 이 임시 값이 데이터베이스 생성 값으로 대체됩니다.
다음은 이 작동 방식을 보여주는 예입니다.말합니다MyEntity
에 의해 됩니다.MyOtherEntity
재산을 경유하여.MyEntityId
앞에 것saveChanges
이 호출됩니다.
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
전화하기 전에 ID를 검색할 수 있습니다..SaveChanges()
Hi/Lo 알고리즘을 사용합니다.ID는 객체가 dbcontext에 추가되면 객체에 할당됩니다.
fluent api를 사용한 구성 예:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity>(e =>
{
e.Property(x => x.Id).UseHiLo();
});
}
관련 마이크로소프트 기사에서 발췌:
Hi/Lo 알고리즘은 변경을 커밋하기 전에 고유한 키가 필요할 때 유용합니다.요약하자면, Hi-Lo 알고리즘은 테이블 행에 고유 식별자를 할당하지만 해당 행을 데이터베이스에 즉시 저장하지는 않습니다.이렇게 하면 일반 순차적 데이터베이스 ID에서 발생하는 것처럼 식별자를 즉시 사용할 수 있습니다.
tblTest 엔티티가 연결할 다른 엔티티에 연결되어 있는 경우 관계를 생성하기 위해 ID가 필요하지 않습니다.tblTest가 다른 Test 개체에 연결되어 있다고 가정해 보겠습니다. 다른 Test 개체에서 tblTest 개체 및 tblTestId 속성을 가지고 있는 경우 다음 코드를 가질 수 있습니다.
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);
anotherTest.tblTest = entity;
....
}
}
제출 후에는 관계가 생성되므로 ID 등에 대해 걱정할 필요가 없습니다.
@zmbq가 맞습니다, 변경 사항 저장을 호출한 후에만 ID를 얻을 수 있습니다.
데이터베이스의 생성된 ID에 의존하지 않는 것이 좋습니다.데이터베이스는 응용프로그램의 세부 정보만 사용해야 하며, 통합 및 변경 불가능한 부분은 사용할 수 없습니다.
이 문제를 해결할 수 없는 경우 고유성 때문에 GUID를 식별자로 사용합니다. MSSQL은 기본 열 유형으로 GUID를 지원하며 속도가 빠릅니다(INT보다 빠르지는 않지만).
건배.
이를 위한 간단한 해결책은 다음과 같습니다.
var ParentRecord = new ParentTable () {
SomeProperty = "Some Value",
AnotherProperty = "Another Property Value"
};
ParentRecord.ChildTable.Add(new ChildTable () {
ChildTableProperty = "Some Value",
ChildTableAnotherProperty = "Some Another Value"
});
db.ParentTable.Add(ParentRecord);
db.SaveChanges();
어디에ParentTable
그리고.ChildTable
Foregin 키로 연결된 두 개의 테이블입니다.
다음과 같이 ChangeTracker에서 값을 조회할 수 있습니다.
var newEntity = new MyEntity();
var newEntity.Property = 123;
context.Add(newEntity);
//specify a logic to identity the right entity here:
var entity = context.ChangeTracker.Entries()
.FirstOrDefault(e => e.Entity is MyEntity myEntity &&
myEntity.Property == newEntity.Property);
//In this case we look up the value for an autogenerated id of type int/long
//it will be a negative value like -21445363467
var value = entity.Properties?
.FirstOrDefault(pe => pe.Metadata.GetColumnName() == nameof(MyEntity.Id))?.CurrentValue;
//if you set it on another entity, it will be replaced on SaveChanges()
설정은 mysql 5.7이었지만 다른 환경에서도 작동해야 합니다.
언급URL : https://stackoverflow.com/questions/17523568/entity-framework-retrieve-id-before-savechanges-inside-a-transaction
'programing' 카테고리의 다른 글
Microsoft SQL Server Management Studio 열기 오류 (0) | 2023.06.28 |
---|---|
refspec을 사용하여 Git 태그를 분기에 푸시하는 방법은 무엇입니까? (0) | 2023.06.28 |
MySQL: 8.0.31 - 몇 개월 사용 후 ID 필드에 큰 차이(수천 개)가 발생합니다. (0) | 2023.06.28 |
Git에서 현재 수정본이 무엇인지 어떻게 알 수 있습니까? (0) | 2023.06.28 |
Spring Boot 프로젝트에 메서드 기반 보안을 추가하려면 어떻게 해야 합니까? (0) | 2023.06.28 |