inflearn logo
강의

講義

知識共有

[C#とUnityで作るMMORPGゲーム開発シリーズ] Part8: Entity Framework Core

EntityState.Unchanged로 처리 후 데이터베이스 조회시 다른 필드값이 null인 경우에 대한 질문

317

Michael Lee

投稿した質問数 3

0

안녕하세요?  Rookiss님.

몬스터가 드랍하는 아이템중에 stackable 아이템이 있어서 DB 조회없이 바로 갯수를 업데이트하고자 하여 아래와 같이 코드를 작성했습니다. 그 후에 다시 인벤토리 아이템을 클라에 통보하기 위하여 조회를 했으나 Stackable Item의 다른 Property가 모두 NULL이 되어 버리네요.  그래서 결국 아이템을 조회한 후에 갯수를 추가하니 정상적으로 처리가 되네요.

질문1 : 이런 경우 entityState를 사용하지 못하고 꼭 데이터베이스에 조회를 해야할 까요?

질문2 : stackable Item의 경우라면 어떤 로직으로 처리를 하는 게 바람직할 지 조언을 부탁드리고자 합니다.

------------------------------------------------------------------------------------

구글링을 통해 stackoverflow에서 찾아본 결과는 아래와 같습니다.

stackoverflow의 답변

https://stackoverflow.com/questions/28479933/after-setting-entitystate-unchanged-the-entity-properties-are-lost

=> 채택된 답변은 아이템의 갯수를 업데이트하기 전에 먼저 조회를 하라고 합니다.

------------------------------------------------------------------------------------

제가 작성중인 Dbtransaction 클래스의 메서드입니다.

------------------------------------------------------------------------------------

public static void RewardStackableItem(Player player, GameRoom room, int itemDbId, int totalCount)

{

if (player == null || room == null || itemDbId == 0)

return;

ItemDb oldItemDb = new ItemDb()

{

ItemDbId = itemDbId,

Count = totalCount

};

// YOU

Instance.Push(() =>

{

S_UpdateItem updateItemPacket = new S_UpdateItem();

using (AppDbContext db = new AppDbContext())

{

// 방법1.  EntityState 로 처리

//db.Entry(oldItemDb).State = EntityState.Unchanged;

//db.Entry(oldItemDb).Property(nameof(ItemDb.Count)).IsModified = true;

// 방법2 : 데이터베이스에 조회를 한 후에 처리

ItemDb item = db.Items

.Single(i => i.OwnerDbId == player.PlayerDbId && i.ItemDbId == itemDbId);

item.Count = totalCount;

bool success = db.SaveChangesEx();

if (success)

{

//문제가 발생하는 부분으로 인벤토리의 해당 아이템을 수정하지 않고 그냥 조회 후 인벤토리를 clear한 후에 다시 인벤토리의 아이템을 만들어서 클라에 통보하고자 하였습니다.

List<ItemDb> items = db.Items

.Where(i => i.OwnerDbId == player.PlayerDbId).ToList();

 

player.Inven.Items.Clear();

// Me

room.Push(() =>

{

                     foreach (ItemDb itemDb in items)

{

Item item = Item.MakeItem(itemDb);

if (item != null)

{

player.Inven.Add(item);

ItemInfo info = new ItemInfo();

info.MergeFrom(item.Info);

updateItemPacket.Items.Add(info);

}

}

player.Session.Send(updateItemPacket);

});

}

}

});

}

EntityState EF-Core ORM

回答 2

1

Michael Lee

답변 감사합니다.

현재 방치형 MMORPG를 만들기에 아이템 드랍이 너무 많아서 Rookiss님이 말씀해주신 부분에서 2번으로 갔습니다. Rookiss님이 강의하신 소스를 기반으로 인벤토리도 만들고 있거든요. 아침에 적용해보니 잘 되는군요.

마지막으로 unchanged가 호출되면 다른 필드의 값은 전부 DbContext상에서는 null 상태가 되고 그 후에 다른 클래스 어디에서 호출해도 결국 null이 되는 것이겠죠? => 요 부분도 테스트해봐야겠습니다. 

늘 루키스님에게 정말 감사하고 빨리 C++ Unreal Engine 부분도 강좌 나왔으면 합니다.

건강 유의하세요.

0

Rookiss

1)
ORM 특성상 조금 비효율적이라도
한번 Read(조회) 하고 다시 수정해서
Commit하는 방식이 가장 정석적이긴 합니다.

2)
1번이 정 마음에 안든다면, 서버 메모리에서도 Player의 Inventory 상태를
완전히 동일하게 메모리에서 들고 있고 (최초 접속 시 해당 플레이어의 모든 데이터를 db에서 로드)
disconnected 상태로 EF Core를 조작해 원하는 부분'만' 수정하고
데이터를 읽을 때 db에서 긁는게 아니라
서버 메모리상의 데이터를 클라에 보내주면 됩니다.

3)
그것도 아니라면 걍 SQL 쿼리를 직접 만들어서 보내 버려도 됩니다.

개발 속도에 중점을 둔다면 1번을,
그게 아니라 최대한 성능에 초점을 둔다면 2번을 선택할 것 같지만
사실 아주 큰 상관은 없고 현재 만드시는 게임 장르에 따라 또 달라질 수 있습니다.

C#으로 DB를 만든다음에 어떻게 외부에서 사용하나요??

0

1034

1

git tool

0

387

1

아이템만 추가로 생성하고 싶은데 문제가 있습니다.

0

407

1

sql server 개체 탐색기가 보이지 않습니다

2

1261

2

17:33 Guild Update1vM시 질문입니다.

0

395

1

ChangeTracker에서 발생한 에러입니다

0

419

1

GetAverageReviewScore의 Data Annotation, FluentAPI, 사용 시 질문입니다.

0

345

1

Table Splitting에서 발생하는 에러 - EventItem is Mapped on "Item"

0

356

1

Fluent API로 FK를 설정할 때 발생하는 에러

0

386

1

[마이그레이션 질문] 테이블 데이터 백업

0

326

1

SELECT 후에 디비 업데이트 질문이 있습니다

0

275

1

게임 기획과 연결해 생각하기

0

291

1

강의 내용 중복 문의

0

290

1

Unhandled exception

0

530

1

영상 8:24분에 내용이 중복됩니다.

0

309

1

InitalizeDB시 에러 문제..

0

412

1

콘솔앱(.NET Core)가 보이지 않아요.

0

1566

1

FK와 JOIN

0

386

1

유니티에서 하드코딩으로 게임 개발이 가능할까요?

1

625

2

UDF 관련해서 질문드립니다.

0

204

1

Table Splitting 부분에서 사소한 에러에 대해 질문이 있어요

1

242

2

몇 가지 질문이 있습니다!

0

215

1

DB연결할 때 연결문자열을 넣잖아요?

1

750

1