programing

엔티티 프레임워크 - 트랜잭션 내부의 'Save Changes' 앞에서 ID 검색

newstyles 2023. 6. 28. 21:25

엔티티 프레임워크 - 트랜잭션 내부의 '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 = xy.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그리고.ChildTableForegin 키로 연결된 두 개의 테이블입니다.

다음과 같이 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