2013-04-18 3 views
29

Überarbeitete gesamte Post.Wie Id mit Entity Framework zu generieren und zu inkrementieren

Ich versuche, die folgende JSON-POST-Anfrage über Fiddler zu schreiben:

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

Allerdings erhalte ich diese Fehlermeldung:

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 

Obwohl, wenn ich manuell eine zufällige Id sendet zusammen mit Die Anfrage ist dann alles gut. Wie folgt:

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

Warum generiert Entity Framework die IDs nicht und erhöht sie automatisch? Meine POCO-Klasse ist wie folgt:

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; } 
} 

Hier ist die Controller-Methode. Wenn im Debug-Modus und ich die Anfrage über Fiddler senden bricht es bei db.SaveChanges(); und gibt den Fehler ein wenig über.

// 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); 
     } 
    } 

Was ist los?

Lösung

Change string Id statt int und Daten Anmerkungen entfernen. Die Id in UserId umbenannt, immer noch der Konvention folgend, und bei Bedarf in anderen POCOs Änderungen vorgenommen, um den Änderungen zu entsprechen.

+1

Wenn Sie Ihren Controller Schritt für Schritt debuggen, erhalten Sie einen Fehler bei db.SaveChanges()? Vielleicht ein Entitätsvalidierungsfehler? –

Antwort

32

Dies ist eine Vermutung :)

Ist es, weil die ID ist eine Zeichenfolge? Was passiert, wenn Sie es in int ändern?

ich meine:

public int Id { get; set; } 
+0

Ich fühle mich wirklich albern, aber es ist ziemlich offensichtlich für mich jetzt, dass es "int" hätte sein sollen. Es ist nur so, dass alles begann, als ich anfing, eine Art "String" war und ich habe es irgendwie vergessen. Danke;) – brk

+0

Ein weiterer Hinweis wäre ** nicht ** zu vergessen, dass die Felder/DB-Spalten als ** Eigenschaften ** in Ihrem Modell ausgedrückt werden müssen und nicht nur einfache Felder/Mitglieder. – Dr1Ku

0

versuchen, eine gültige Json mit Anführungszeichen schreibt:

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

Sie haben einen schlechten Tabellenentwurf. Sie können eine Zeichenfolge nicht automatisch inkrementieren, das macht keinen Sinn. Sie haben grundsätzlich zwei Möglichkeiten:

1.) ID-Typ ändern in int statt String
2.) nicht empfohlen !!! - Autoincrement selbständig handhaben. Sie müssen zuerst den neuesten Wert aus der Datenbank abrufen, ihn auf die ganze Zahl analysieren, inkrementieren und erneut als Zeichenfolge an die Entität anhängen. SEHR SCHLECHTE Idee

Erste Option erfordert, jede Tabelle, die einen Verweis auf diese Tabelle hat, zu ändern, ABER es lohnt sich.

+0

Sie haben absolut Recht, es war schlechtes Design von mir. Vielen Dank für Ihre Eingabe :) – brk

+0

Re: nicht empfohlen !!! - Dem stimme ich nicht zu.Autoincrement von der db durchgeführt bedeutet, dass Sie die db treffen müssen, um einen Datensatz zu erstellen, der nicht immer groß ist. Aber das ist ein anderes Thema ... – mayu

+1

@Tymek, ähm, wie auch immer du die Datenbank treffen musst, um festzustellen, welche ID als nächstes kommen soll. Aber, wenn Sie die Datenbank für Sie behandeln lassen, übergeben Sie einfach andere Parameter an die db und db berechnet den Wert für Sie während der Behandlung der Einfügung.Wenn Sie die automatische Inkrementierung von selbst behandeln, müssen Sie die neueste ID aus erhalten die Datenbank, BEVOR Sie tatsächlich eine Abfrage senden, um einen Datensatz einzufügen. Das ist eine zusätzliche Reise nach db! Wenn Sie nicht auf die Situation eingehen, wenn Ihre Datenbank von mehr als einer Anwendung/einem Benutzer gleichzeitig zugegriffen wird, ist das wirklich ein Albtraum, den es zu lösen gilt. – walther

Verwandte Themen