

自作 SRPG ゲームのデータを、 Entity Framework の Code-First でデータベースに保存しています。テーブルは
`Character`, `Item`, `Weapon`, `Equipment` などです（中身は名前から想像できるようなもの）。

概ね順調に実装できていたのですが 1 点どうしても解決できません。

それは `SaveChanges()` を呼ぶまでオートインクリメントの ID が発番されず `0` のままな事です。 SRPG
の場合は途中でセーブしないためゲーム中はすべて `.Local`
キャッシュに対してのみ読み/書き/挿入/削除します。そうすると途中で入手したアイテムをデータベースに挿入しても `ID=0` のままになり一意なアイテムID
を期待するプログラムから (セーブするまで）利用できません。このまま削除できないことがあると一番困ります。

ゲームで Entity Framework を利用するときに誰もが困ると思うのですが、どのような解決方法が考えられるでしょうか。


CC BY-SA 3.0
2015-01-08T10:31:28.003
4291
2015-01-08T13:24:01.973
2015-01-08T12:02:22.467
33
5005
question
c# .net entity-framework
EntityFramework: `SaveChanges()` 以外でオートインクリメントの ID を発番するには？


Identityではなく`Interlocked`や`Guid`を利用して独自に採番するのが良いと思います。  
クライアントが複数存在するのであれば、キーを64ビットにして上位32ビットは起動単位でDB採番し、下位32ビットは`Interlocked`を使用するという手もあります。

## 追記

`DataSet`などで使われる方法として、保存前に仮Idを割り当てる手法があります。この場合`[DatabaseGenerated(DatabaseGeneratedOption.Identity)]`と`Interlocked`を併用して

[code]

    public class Hoge
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
    
        private static int _TempId;
    
        public static Hoge NewHoge()
        {
            return new Hoge()
            {
                // 仮のIdが-1から順に採番される。
                Id = Interlocked.Decrement(ref _TempId)
            };
        }
    }
    
[/code]

のようにエンティティを定義し、新規レコード作成時にはNewXXXを呼ぶようにします。

いずれにせよ外部キー項目には明示的に実装しない限り反映されませんので注意が必要です。


CC BY-SA 3.0
2015-01-08T10:57:48.500
4293
2015-01-08T13:24:01.973
2015-01-08T13:24:01.973
5750
5750
4291
answer