대형 프로젝트 - C# + 유니티로 만드는 MMORPG 게임 개발/(5) EF Core

Entity 상태 관리

monstro 2025. 8. 11. 11:19
728x90
반응형

- 개요

EF Core에서 사용하는 Entity에는 총 5가지의 상태가 존재합니다.

각각 다음과 같습니다.

  • 1) Detached : No Tracking 상태이므로 SaveChanges를 해도 갱신되지 않음
  • 2) Unchanged : 로컬과 DB에 존재하되 수정하지 않은 상태이므로 SaveChanges를 해도 갱신되지 않음
  • 3) Deleted : 로컬과 DB에 존재하지만 삭제할 예정인 상태, SaveChanges를 통해 갱신해야 함
  • 4) Modified : 로컬에서만 수정되어 DB에 적용되지 않은 상태, SaveChanges를 통해 갱신해야 함
  • 5) Added : 로컬에만 존재하고 DB에는 존재하지 않는 상태, SaveChanges를 통해 DB에 적용해야 함

 

1) State의 확인 - DBCommands 클래스

...

public static void CreateTestData(AppDBContext db)
{
    var Kim = new Player() { Name = "Kim" };
    var Choi = new Player() { Name = "Choi" };
    var Park = new Player() { Name = "Park" };

    // 첫 번째 State 출력
    Console.WriteLine(db.Entry(Kim).State);

    List<Item> items = new List<Item>()
    {
        new Item()
        {
            TemplateId = 101,
            CreateDate = DateTime.Now,
            Owner = Kim
        },
        new Item()
        {
            TemplateId = 102,
            CreateDate = DateTime.Now,
            Owner = Choi
        },
        new Item()
        {
            TemplateId = 103,
            CreateDate = DateTime.Now,
            Owner = Park
        }
    };

    Guild guild = new Guild()
    {
        GuildName = "G1",
        Members = new List<Player>() { Kim, Choi, Park }
    };

    db.Items.AddRange(items);
    db.Guilds.AddRange(guild);

    // 두 번째 State 출력
    Console.WriteLine(db.Entry(Kim).State);

    db.SaveChanges();

    // 세 번째 State 출력
    Console.WriteLine(db.Entry(Kim).State);
}

 

CreateTestData 함수에 위와 같이 3개의 출력문을 추가하였습니다.

DbContext의 Entry 함수를 사용하여 Entity에 대한 State를 가져오도록 설정하였습니다.

가져오는 순서는 다음과 같습니다.

  • Entity를 생성한 시점
  • 로컬에서 생성한 Entity를 통해 데이터 테이블을 수정한 시점 
  • SaveChanges 함수를 호출한 시점

 

 

실행 결과는 위와 같습니다.

  • 첫 번째 시점 : Entity가 방금 생성되어 추적되지 않는 상태
  • 두 번째 시점 : 로컬에서만 Entity가 존재하고 DB에는 존재하지 않는 상태
  • 세 번째 시점 : 로컬과 DB 양쪽에서 Entity가 존재하되 수정하지 않은 상태

따라서 의도한 대로 State가 출력되는 것을 확인할 수 있습니다.

 

2) SaveChanges 함수의 동작 원리 - DBCommands 클래스

SaveChanges 함수를 호출하게 되면 DB에 추가한 Entity들Unchanged 상태로 변경됩니다.
이때 내부적으로 SQL의 Identity 함수를 사용하여 Primary Key를 관리하는데,
Entity를 추가한 후에 ID를 받아와 해당 객체의 ID Property를 설정합니다.

마지막으로 RelationShip을 참고하여 Foreign Key 세팅해당 객체의 참조를 연결합니다.

 

public static void CreateTestData(AppDBContext db)
{
    var Kim = new Player() { Name = "Kim" };
    var Choi = new Player() { Name = "Choi" };
    var Park = new Player() { Name = "Park" };

    List<Item> items = new List<Item>()
    {
        new Item()
        {
            TemplateId = 101,
            CreateDate = DateTime.Now,
            Owner = Kim
        },
        new Item()
        {
            TemplateId = 102,
            CreateDate = DateTime.Now,
            Owner = Choi
        },
        new Item()
        {
            TemplateId = 103,
            CreateDate = DateTime.Now,
            Owner = Park
        }
    };

    Guild guild = new Guild()
    {
        GuildName = "G1",
        Members = new List<Player>() { Kim, Choi, Park }
    };

    db.Items.AddRange(items);
    db.Guilds.AddRange(guild);

    // PK : SaveChanges 함수 호출 이전
    Console.WriteLine(Kim.PlayerId);
    // FK : SaveChanges 함수 호출 이전
    Console.WriteLine(items[0].Owner.PlayerId);

    db.SaveChanges();

    // PK : SaveChanges 함수 호출 이후
    Console.WriteLine(Kim.PlayerId);
    // FK : SaveChanges 함수 호출 이후
    Console.WriteLine(items[0].Owner.PlayerId);
}

 

CreateTestData 함수를 위와 같이 수정하였습니다.

PlayerKim 객체에 대한 Primary KeyItem의 첫번째 객체에 대한 Foreign Key를 출력하되,

SaveChanges 함수 호출 이전과 이후로 구분하여 출력합니다.

 

 

출력 결과는 위와 같습니다.

SaveChanges 함수호출하기 이전의 값은 0으로 설정되었지만,

함수를 호출한 이후의 Key 프로퍼티의 값은 1로 설정되었습니다.

 

3) 이미 존재하는 객체를 외래키로 연결

 

이미 존재하는 객체외래키로 연결하는 방법은 위와 같습니다.

  • 우선 Tracked Instance 즉, 추적되는 객체가져와야 합니다.
  • 이어서 데이터를 연결하면 이미 존재하는 객체외래키로 연결할 수 있습니다.
728x90
반응형

'대형 프로젝트 - C# + 유니티로 만드는 MMORPG 게임 개발 > (5) EF Core' 카테고리의 다른 글

Connected와 Disconnected  (0) 2025.08.11
Update 기초  (0) 2025.08.11
Data Transfer Object  (0) 2025.08.05
데이터 로딩  (0) 2025.08.05
Relationship 기초  (0) 2025.08.04