web-dev-qa-db-ja.com

Entity FrameworkでIDを生成して自動インクリメントする方法

改訂投稿全体。

次のJSON POSTリクエストをFiddler経由で投稿しようとしています。

{Username:"Bob", FirstName:"Foo", LastName:"Bar", Password:"123", Headline:"Tuna"}

しかし、私はこのエラーを受け取っています:

Message "Cannot insert the value NULL into column 'Id', table 'xxx_f8dc97e46f8b49c2b825439607e89b59.dbo.User'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated." string

ただし、リクエストと一緒にランダムIDを手動で送信した場合は、すべて問題ありません。そのようです:

{Id:"1", Username:"Bob", FirstName:"Foo", LastName:"Bar", Password:"123", Headline:"Tuna"}

Entity FrameworkがIDを生成および自動インクリメントしないのはなぜですか?私のPOCOクラスは次のとおりです。

public class User
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public string Id { get; set; }
    public string Username { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Password { get; set; }
    public string Headline { get; set; }
    public virtual ICollection<Connection> Connections { get; set; }
    public virtual ICollection<Address> Addresses { get; set; }
    public virtual ICollection<Phonenumber> Phonenumbers { get; set; }
    public virtual ICollection<Email> Emails { get; set; }
    public virtual ICollection<Position> Positions { get; set; }
}

public class Connection
{
    public string ConnectionId { get; set; }
    public int UserId { get; set; }
    public virtual User User { get; set; }
}

public class Phonenumber
{
    public string Id { get; set; }
    public string Number { get; set; }
    public int Cycle { get; set; }
    public int UserId { get; set; }
    public User User { get; set; }
}

これがコントローラーメソッドです。デバッグモードでFiddlerを介してリクエストを送信すると、db.SaveChanges();で中断し、少し上のエラーが表示されます。

    // POST api/xxx/create
    [ActionName("create")]
    public HttpResponseMessage PostUser(User user)
    {
        if (ModelState.IsValid)
        {
            db.Users.Add(user);
            db.SaveChanges();

            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, user);
            response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = user.Id }));
            return response;
        }
        else
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        }
    }

どうしましたか?

ソリューション

代わりに文字列IDをintに変更し、データ注釈を削除します。 Idの名前をUserIdに変更し、引き続き慣習に従い、必要に応じて他のPOCOで変更を加えて変更と一致させました。

41
brk

これは推測です:)

IDが文字列だからでしょうか? intに変更するとどうなりますか?

というのは:

 public int Id { get; set; }
43
tymtam

テーブルのデザインが悪い。文字列を自動インクリメントすることはできません。これは意味がありません。基本的に2つのオプションがあります。

1.)IDのタイプを文字列ではなくintに変更します
2。)非推奨!!! -自分で自動インクリメントを処理します。最初にデータベースから最新の値を取得し、それを整数に解析し、増分し、再び文字列としてエンティティにアタッチする必要があります。非常に悪い考え

最初のオプションでは、このテーブルへの参照を持つすべてのテーブルを変更する必要がありますが、それだけの価値があります。

8
walther