Revisado post entero.

Estoy tratando de publicar la siguiente JSON solicitud POST a través de Fiddler:

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

Sin embargo estoy recibiendo este error:

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

Aunque si puedo enviar manualmente un Id aleatorio junto con la solicitud, todo es bueno. Así:

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

¿Por qué Entity Framework, no se generará y el incremento automático de la Id? Mi clase POCO es como sigue:

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

Aquí es el método de controlador. Cuando en modo de depuración y puedo enviar la solicitud a través de el Violinista en el que se rompe en db.SaveChanges(); y da el error visto un poco por encima.

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

Lo que está mal?

Solución

Cambio string Id int en lugar y eliminar anotaciones de Datos. Cambiado el nombre de la Id a id de usuario, aún después de la convención, e hizo los cambios donde sea necesario, en otros POCO para que coincida con los cambios.

  • Al depurar su controlador, paso por paso, tienes un error en la db.SaveChanges()? Tal vez una entidad de error de validación?
InformationsquelleAutor brk | 2013-04-18

2 Comentarios

  1. 44

    Esto es una suposición 🙂

    Es porque el IDENTIFICADOR es una cadena? ¿Qué sucede si cambia a int?

    Quiero decir:

     public int Id { get; set; }
    • Me siento muy tonta pero es bastante obvio para mí ahora que debería haber sido int. Es sólo que cuando empecé todo era bastante string y en cierto modo me olvidó. Gracias 😉
    • Otra sugerencia sería no olvidar que los campos/DB Columnas deben ser expresados como propiedades en el Modelo y no simplemente de los campos de los miembros.
  2. 8

    Usted tiene un mal diseño de la tabla. Usted no puede autoincrement una cadena, que no tiene ningún sentido. Usted tiene básicamente dos opciones:

    1.) tipo de cambio de ID para int en lugar de cadena

    2.) no se recomienda!!! – manejar incrementado automáticamente por usted mismo. Primer lugar es necesario obtener el valor más reciente de la base de datos, de análisis para el entero, incremento y adjuntarlo a la entidad como una cadena de nuevo. MUY MALA idea

    Primera opción requiere cambiar cada tabla que tiene una referencia a esta tabla, PERO vale la pena.

    • Tienes toda la razón, fue un mal diseño de mí. Gracias por tu aporte 🙂
    • Re: no se recomienda!!! – No estoy de acuerdo con esto. Autoincrement hecho por el db significa que usted tiene que golpear la base de datos para crear un registro que no siempre es genial. Pero eso es otro tema…
    • erm, de cualquier manera, usted tiene que golpear la base de datos para determinar que el Id debe ser la siguiente. Pero, si vamos a la base de datos a manejar es para usted, usted sólo tiene que pasar otros parámetros a la db y db cifras el valor que tiene para usted durante el manejo de la inserción.Si usted maneja el autoincrementing por sí mismo, tiene que obtener el ultimo id de la base de datos ANTES de enviar una consulta para insertar un registro. Eso es un viaje adicional a db! No mencionar la situación cuando la base de datos se accede por más de una aplicación/usuario en un momento, que en realidad es una pesadilla para resolver.
    • Yo realmente no puedo ver una situación en la que esta podría ser una buena idea.
    • Yo estaba pensando acerca de la generación de id de sí mismo sin llegar a la base de datos (recuerde, no necesita ser id++). Para algunas de las razones por las que autoincrement (y más genral de la db manejo ids) no es tan buena ave un vistazo a ayende.com/blog/3915/… En mi opinión autoincrement tarde o temprano causa dolor.
    • sí, Id puede ser cualquier cosa, pero ¿cómo saber que id no se si no le das a la primera base de datos para comprobar?? Tiene que ser único, por lo que debe tener un mecanismo que tener cuidado con esto. La situación más compleja, más el dolor de su aplicación, especialmente en escenarios simultáneos (como ASP.NET que es esto de la pregunta acerca de), donde usted necesita para manejar esto para todos los usuarios que tienen acceso a la bd a la vez. ¿Qué pasa si usted crea un Id, que es adoptado? Se le pasa a la base de datos y se obtiene un error. ¿Qué dicen los usuarios? «Uy, nos genera un Identificador incorrecto, intentemos de nuevo»??
    • hay una palabra que se ajusta a esa idea de reinventar la rueda. Por lo general, viene con la fractura de otras partes del sistema, como la Unidad de trabajo que Ayende menciona así. Por otra parte, lo que si hay un requisito de la base de datos disponible para otras aplicaciones? Lo que si no quieren usar nhibernate? Tomando db responsabilidades lejos de la db no es nunca una buena idea, no importa que diga lo contrario…
    • En el contexto de esta pregunta que está a la derecha. Para un contexto más general de la generación de identificadores este no es el lugar adecuado para discutir el tema.
    • Guid puede ser almacenado como una cadena de texto y no es necesario golpear la base de datos para ver si ya existe.

Dejar respuesta

Please enter your comment!
Please enter your name here