2013-04-18 23 views
29

改訂ポスト全体。Entity Frameworkで自動インクリメントIDを生成および自動生成する方法

{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を送信する場合、私はバイオリンを経由して、次のJSON POSTリクエストを投稿しようとしている

その要求はすべて良いです。同様に:

{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で必要に応じて変更を加えて変更に合わせる。引用符で囲まれた文字列で有効なJSONを投稿

+1

コントローラをデバッグすると、ステップバイステップでdb.SaveChanges()でエラーが発生しますか?おそらくエンティティ検証エラーですか? –

答えて

32

これは推測です:)

がそれですか?それをintに変更するとどうなりますか?

私は意味:

public int Id { get; set; } 
+0

私は本当にばかげていると感じますが、今はintであったはずです。それは、私がすべてを始めたとき、それはかなりストリングであり、私はそれを忘れてしまった。ありがとう;) – brk

+0

もう一つのヒントは、フィールド/ DB列が単純なフィールド/メンバーではなく、モデル内の**プロパティ**として表現される必要があることを忘れるためではありません。 – Dr1Ku

0

試み:IDが文字列であるため、

{ 
    "Username": "test", 
    "FirstName": "foo", 
    "LastName": "bar", 
    "Password": "123", 
    "Headline": "Tuna" 
} 
6

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

1.)IDのタイプを文字列の代わりにintに変更します。
2.)推奨しません。 - あなた自身で自動インクリメントを処理します。最初に、データベースから最新の値を取得し、それを整数に解析し、インクリメントしてエンティティに文字列として再度添付する必要があります。非常に悪い考え方

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

+0

あなたは絶対に正しいです、それは私の悪いデザインでした。あなたの入力をありがとう:) – brk

+0

Re:推奨しない! - 私はこれに同意しない。dbによって行われる自動インクリメントは、必ずしも大きくないレコードを作成するためにdbをヒットする必要があることを意味します。しかしそれはもう一つの話題です... – mayu

+1

@Tymek、erm、いずれの方法でも、あなたは次のIDを決定するためにデータベースにヒットする必要があります。しかし、データベースで処理できるようにする場合は、dbとdbに他のパラメータを渡すだけで、insertの処理中に値が決まります。自分で自動インクリメントを処理する場合は、最新のIDを取得する必要があります。実際にレコードを挿入するためにクエリを送信する前に、データベース。それはdbへの余分な旅行です!一度に複数のアプリケーション/ユーザーがデータベースにアクセスする状況は言及していませんが、それは本当に解決すべき悪夢です。 – walther