2013-04-18 14 views
29

Revisionato post completo.Come generare e incrementare automaticamente Id con Entity Framework

Sto cercando di inviare la seguente richiesta JSON POST via Fiddler:

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

Comunque sto ottenendo questo errore:

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 

Anche se inviare manualmente un ID casuale insieme la richiesta quindi è tutto ok Mi piace così:

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

Perché Entity Framework non genera e incrementa automaticamente l'ID? La mia classe POCO è la seguente:

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

Ecco il metodo del controller. Quando in modalità di debug e invio la richiesta tramite Fiddler, si interrompe a db.SaveChanges(); e dà l'errore visto un po 'sopra.

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

Cosa c'è che non va?

Soluzione

Modifica stringa di identificazione a int invece e rimuovere le annotazioni di dati. Rinominato l'Id in UserId, sempre seguendo la convenzione, e apportato le modifiche, se necessario, in altri POCO per corrispondere alle modifiche.

+1

Quando esegui il debug del controller, passo dopo passo, ricevi un errore su db.SaveChanges()? Forse un errore di validazione dell'entità? –

risposta

32

Questa è una supposizione :)

Forse perché l'ID è una stringa? Cosa succede se lo cambi in int?

Voglio dire:

public int Id { get; set; } 
+0

Mi sento davvero sciocco ma è abbastanza ovvio per me ora che avrebbe dovuto essere "int". È solo che quando ho iniziato tutto era praticamente una 'stringa 'e in un certo senso me ne sono dimenticato. Grazie;) – brk

+0

Un altro suggerimento sarebbe ** non ** dimenticare che i campi/colonne DB devono essere espressi come ** proprietà ** nel modello e non solo campi/membri semplici. – Dr1Ku

0

prova a pubblicare una JSON valido stringhe tra virgolette:

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

avete un disegno tavolo male. Non è possibile eseguire l'autoincremento di una stringa, il che non ha alcun senso. Esistono fondamentalmente due opzioni:

1.) cambiare il tipo di ID a int invece di stringa
2.) non consigliato !!! - Gestisci l'autoincremento da solo. È prima necessario ottenere l'ultimo valore dal database, analizzarlo all'intero, incrementarlo e collegarlo nuovamente all'entità come una stringa. Idea MOLTO CATTIVA

Prima opzione richiede di cambiare ogni tabella che ha un riferimento a questa tabella, MA ne vale la pena.

+0

Hai perfettamente ragione, è stato un cattivo disegno di me. Grazie per il tuo contributo :) – brk

+0

Re: not recommended !!! - Non sono d'accordo con questo.Autoincrement fatto dal db significa che devi colpire il db per creare un record che non è sempre ottimo. Ma questo è un altro argomento ... – mayu

+1

@Tymek, erm, in entrambi i casi devi colpire il database per determinare quale ID dovrebbe essere il prossimo. Ma se lasci che il database lo gestisca per te, semplicemente passi altri parametri al db e db calcola il valore per te durante la gestione dell'inserto. Se gestisci l'autoincrementamento da solo, devi ottenere l'ultimo ID da il database PRIMA di inviare effettivamente una query per inserire un record. Questo è un viaggio in più per db! Non menzionando la situazione in cui il tuo database viene visitato da più di un'applicazione/utente alla volta, è davvero un incubo da risolvere. – walther