엔터티 프레임 워크에서 삽입 된 엔터티 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 인치) ObjectSet와 SaveChanges관련에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.