엔터티 프레임 워크에서 삽입 된 엔터티 ID를 얻으려면 어떻게해야합니까? [닫은]


611

Asp.net의 Entity Framework에 문제가 있습니다. 데이터베이스에 객체를 추가 할 때마다 ID 값을 얻고 싶습니다. 어떻게해야합니까?


16
아래의 Ladislav Mrnka의 답변이 정답이므로 그대로 수락해야합니다.
CShark

3
OP는 자신의 계정으로 한 번만 게시되었으며이 질문은 더 구체적입니다. 이로 인해 거의 2k의 명성 (!)을 얻었으며 그날 이후 계정이 폐기되어 답변이 수락 된 것으로 표시되지 않았습니다.
MurariAlex

1
외래 키 관계에서 사용하기 위해 ID가 필요한 경우 대신 종속 엔터티의 탐색 속성을 이전에 추가 된 엔터티로 설정하는 것을 고려할 수 있습니다. 이렇게 SaveChanges하면 ID를 얻기 위해 즉시 전화하는 것에 대해 신경 쓸 필요가 없습니다 . 자세한 내용은 여기를 참조하십시오 .
B12Toaster

Entity Framework Core 3.0의 경우 acceptAllChangesOnSuccess 매개 변수를 true로 추가하십시오. await _context.SaveChangesAsync (true);
Mike

답변:


1005

꽤 쉽습니다. 당신이 사용하는 경우 DB는 (같은 ID를 생성 IDENTITY당신은 단지에 개체를 추가 할 필요가 MS SQL 인치) ObjectSetSaveChanges관련에ObjectContext . Id자동으로 채워집니다 :

using (var context = new MyContext())
{
  context.MyEntities.Add(myNewObject);
  context.SaveChanges();

  int id = myNewObject.Id; // Yes it's here
}

기본적으로 엔티티 프레임 워크는 자동 생성 이 사용될 때 각각 INSERT을 따릅니다 .SELECT SCOPE_IDENTITY()Id


34
그래서 당신은 잘못된 질문을하고 있습니다. 예외에 문제가있는 경우 예외 (및 내부 예외) 및 해당 오류를 발생시키는 코드 조각을 보여주는 질문을해야합니다.
Ladislav Mrnka

3
추가하는 엔티티가 유효한 엔티티인지 확인하십시오. 예를 들어, 데이터베이스 제한이 "null이 아님"인 모든 항목을 채워야합니다.
fran

4
@LadislavMrnka : 새로 생성 된 객체의 탐색 속성은 어떻습니까? 변경 사항을 저장 한 후 자동으로 채워지지 않는 것 같습니다.
Isaac Kleinman 18

4
다음 시나리오를 고려해 봅시다 : table1은 @@ identity를 생성하여 table2에서 사용합니다. table1과 table2는 모두 같은 트랜잭션에 있어야합니다. 예를 들어 하나의 SaveChange 조작은 두 테이블의 데이터를 모두 저장해야합니다. 'SaveChanges'가 호출되지 않으면 @@ identity가 생성되지 않습니다. 이 상황을 어떻게 해결할 수 있습니까?
Arash

7
@ Djeroen : 데이터베이스 생성 ID를 사용하는 경우 먼저 해당 객체를 데이터베이스에 삽입해야합니다. 삽입 전에 ID가 필요한 경우 데이터를 삽입하기 전에 고유 ID를 얻기 위해 고유 한 논리를 작성해야하며 데이터베이스에서 ID 열을 사용하지 마십시오.
Ladislav Mrnka

124

나는 Ladislav Mrnka의 대답을 사용하고 있었다 내가 있었다 때문에 내가 여기에 게시하고 그러나 엔티티 프레임 워크를 사용하는 경우 ID를 검색 성공적으로 미스 - 사용 (즉이 필요하지 않은 그것을 사용)을하고 난 인 - 여기 내 결과를 게시 줄 알았는데 사람들은 내가 가진 문제를 "해결"하려고합니다.

고객과 외래 키 관계가있는 주문 오브젝트를 고려하십시오. 새로운 고객과 새로운 주문을 동시에 추가했을 때 이와 같은 일을하고있었습니다.

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를 처음 접하는 개발자는 필요하지 않은 것에 대해 최고 투표 답변을 과도하게 사용하는 데 도움이 될 수 있다고 생각했습니다.

이는 단일 트랜잭션에서 업데이트가 완료되어 orphin 데이터를 피할 수 있음을 의미합니다 (모든 업데이트가 완료되거나 완료되지 않음).


8
감사 ! 중요 모범 사례 팁 : var order = new Order {고객 = 고객}; 이것은 관련 개체를 할당하는 Entity Framework의 힘을 보여 주 고 Id가 자동으로 업데이 트됩니다.
LA Guy 88

답변에 추가 정보를 주셔서 감사합니다. EF를 사용할 때 DB 왕복을 저장하는 데 매우 도움이되었습니다.
Prasad Korhale

정말 감사합니다. 이것이 바로 내가 찾던 것입니다. 방금 "SaveChanges"를 두 번 호출하는 것보다 더 나은 방법이있을 수 있다고 생각했습니다.
Josh

1
또한 거래 행동을 해결한다고 답에 굵은 글씨로 표시하십시오. 개체 중 하나를 추가하지 못하면 트랜잭션의 일부가 성공하지 못합니다. 예 : 사람과 학생 추가. 사람이 성공하고 학생이 실패합니다. 이제 사람은 중복됩니다. 이 훌륭한 솔루션에 감사드립니다!
Imran Faruqi

32

변경 사항을 저장 한 후 엔터티를 다시로드해야합니다. EF로 추적 할 수없는 데이터베이스 트리거에 의해 변경 되었기 때문입니다. 따라서 우리는 DB에서 엔티티를 다시로드해야합니다.

db.Entry(MyNewObject).GetDatabaseValues();

그때

int id = myNewObject.Id;

아래 질문에서 @jayantha 답변을보십시오.

defaultValue를 사용할 때 엔티티 프레임 워크에서 삽입 된 엔티티의 ID를 어떻게 얻을 수 있습니까?

아래 질문에서 @christian 답변을 찾는 것도 도움이 될 수 있습니다.

Entity Framework Refresh 컨텍스트?


2
안녕하세요, 이렇게하면 컴파일 오류가 발생합니다 : ID 또는 이름과 같은 속성을 확인할 수 없습니다. 제발 도와 줄 수 있습니까?
Morteza Azizi

1
@MortezaAzizi 처리되지 않거나 null 속성 문제가있는 것 같지만 코드 조각을 더 자세히 설명하거나 작성할 수 있습니까?
QMaster

3
.GetDatabaseValues();방금 모델을 DB에 저장 한 경우 에는 할 필요가 없습니다 . ID가 모델에 자동으로 다시 채워 져야합니다.
vapcguy

3
@QMaster EF가 동일한 SQL 문을 수행 (및 수행) 할 수 있고 개체의 ID를 채우는 것을 제외하고. 그렇지 않으면 여러 종속 개체를 동시에 저장할 수있는 방법은 무엇입니까? GetDatabaseValues()데이터베이스에서 찾을 객체의 ID를 모르는 경우 어떻게 할 수 있습니까?
krillgar

2
@vapcguy 알겠습니다. 귀 기울여 주셔서 감사합니다. 두 가지 버전의 EF ASAP에서 확인하겠습니다.
QMaster

16

이 링크를 참조하십시오.

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
}

7
최고 투표 답변과 동일합니다.
Lewis86

2
StoreGeneratedPattern나를 위해 빠진 조각이었다.
BurnsBA

1
이것이 ORACLE 및 ON-Insert Trigger로 작업 할 때가는 방법입니다.
Karl

링크가 깨진 - 도메인 파킹
t.durden

Oracle에서 안녕하세요 .Entity에서 StoreGeneratedPattern을 설정해야했습니다. 모델 뷰어로 이동하여 테이블과 PK를 찾은 다음 StoreGeneratedPattern 속성을 선택하고 Identity로 설정하십시오. 위의 답변이 나타내는대로 작동합니다. 삽입시 시퀀스에서 PK를 채우는 트리거가있는 경우에 해당합니다.
Rob

15

Id변경 사항을 데이터베이스에 전파 한 후 저장하는 오브젝트가 올바른지 확인하십시오 .


27
내면의 예외를 보았습니까? ;-)
Snowbear

6

저장 한 후에 만 ​​ID를 얻을 수 있으며 대신 새로운 Guid를 생성하고 저장하기 전에 할당 할 수 있습니다.


4

데이터베이스에 데이터를 삽입 해야하는 동시에 엔티티 프레임 워크를 사용하여 기본 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;
 }

4

모든 답변은 자체 시나리오에 매우 적합합니다. 내가 다른 것은 Add ()가 int 변수에 반환 된 객체 (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
}

따라서 전체 새 객체를 만드는 대신 원하는 것을 가져옵니다. :)

Mr. @GertArnold에 대한 편집 :

여기에 이미지 설명을 입력하십시오


3
공개되지 않은 메소드를 추가하여 ID를 할당하는 것은 실제로 유용하지 않습니다. 이것은 Entity Framework와 관련이 없습니다.
Gert Arnold

1
@GertArnold .. 나는 OP와 같은 질문을 받았으며 대답을 찾아 한 줄로 작성 했으며 설명 하지 않는 비공개 메소드 관리 라는 용어를 들어 본 적이 없습니까?
IteratioN7T

3
그것은 당신이하는 모든 것을 보여주지 않는다는 것을 의미합니다. 어쩌면 그것은 명확하게 설명되지 않았을 수도 있습니다. 내가 아는 것은 Add(이것이라면 DbSet.Add) 마술처럼 값을 할당 하지 않는다는EmployeeId입니다.
Gert Arnold

3
없이는 아닙니다 SaveChanges. 불가능한. EmployeeId예를 들어 Employee의 생성자 에서 를 할당하는 다른 프로세스가없는 한 . 또는을 사용하여 EF 코어에 ForSqlServerUseSequenceHiLo있습니다. 어쨌든, 당신은 전체 그림을 제공하지 않습니다.
Gert Arnold

3
마지막 말은 표준 EF 동작이 아닙니다. 환경에 대한 자세한 내용을 제공해야합니다. EF 버전, 데이터베이스 브랜드 및 버전, 직원 클래스, 맵핑 세부 사항.
Gert Arnold

3
Repository.addorupdate(entity, entity.id);
Repository.savechanges();
Var id = entity.id;

작동합니다.


4
리포지토리는 변경 내용을 데이터베이스에 저장하지 않습니다. UnitOfWork의 직업입니다.
tchelidze

5
게다가, 그것이 무엇인지 Repository는 확실하지 않습니다 . 그리고 "이것은 효과가있다"는 설명이다!.
Gert Arnold

2

두 가지 전략이 있습니다.

  1. 데이터베이스 생성 ID( int또는 GUID) 사용

    단점 :

    저장된 엔티티 SaveChanges()를 얻기 위해 수행해야합니다 ID.

    장점 :

    int정체성을 사용할 수 있습니다 .

  2. 클라이언트 생성 ID-GUID 만 사용하십시오 .

    장점 : SaveChanges운영 최소화 . 한 번의 작업으로 새로운 객체의 큰 그래프를 삽입 할 수 있습니다.

    단점 :

    만 허용 GUID


1

EF 6.x 코드를 먼저 사용하는 경우

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

데이터베이스 테이블을 초기화하면

(newsequentialid())

헤더의 Default Value 또는 Binding 아래에있는 테이블 속성에서 ID를 삽입 할 때 채워질 수 있습니다.

문제는 테이블을 생성하고 테이블을 추가하면

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

나중에, 향후 업데이트 데이터베이스는 (newsequentialid ())를 다시 추가하지 않습니다.

올바른 방법을 수정하려면 마이그레이션을 지우고 데이터베이스를 삭제 한 후 다시 마이그레이션하십시오 ... 또는 테이블 디자이너에 (newsequentialid ())를 추가하면됩니다.


newsequentialid ()의 위치를 ​​자세히 설명 할 수 있습니까? 이미 EF 코드를 사용하지 않고 직접 만든 데이터베이스 모델이 있으며 기본 키가 아니기 때문에 ID를 채우지 않습니다. 그에 대한 해결책을 찾고 싶습니다.
조쉬

1
@josh 코드가 Guid 유형이라고 가정하면 Sql Server Management Studio에서 테이블을 마우스 오른쪽 단추로 클릭하고 ID 열을 클릭하면 (일반) 내부의 열 속성 탭 아래에 기본값 또는 바인딩이 표시됩니다. 당신이 손으로 DB 테이블을 작성하는 경우, 참조 NEWSEQUENTIALID 또는 NEWID . 일반적인 사용 사례는 다음과 같습니다when -column- is NULL, then NEWID()
Jeff Li
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.