¿Cómo aseguro que Linq to Sql no anula ni viola valores predeterminados de DB no anulables?

Tengo un DB de SQL Server con una tabla con estos campos:

  1. Un bit con el valor predeterminado 1, NOT NULL .
  2. Un smalldatetime con el valor predeterminado gettime() , NOT NULL .
  3. Un int sin valor predeterminado, IDENTITY , NOT NULL .

Cuando genero Linq a SQL para esta tabla, sucede lo siguiente:

  1. El bit no recibe un tratamiento especial.
  2. El smalldatetime no recibe un tratamiento especial.
  3. El int está marcado como IsDbGenerated .

Esto significa que cuando realice inserciones utilizando Linq a SQL, ocurrirá lo siguiente:

  1. The bit will be sent as 0, overriding the default value. Right?
  2. The smalldatetime will be sent as an uninitialized System.DateTime, producing an error in SQL server since it doesn't fall with the SQL Server smalldatetime range. Right?
  3. The IsDbGenerated int will not be sent; the DB will generate a value which Linq to SQL will then read back.

What changes do I have to make to make this scenario work?

Para resumir: quiero campos no anulables con valores predeterminados asignados por DB, pero no los quiero IsDbGenerated si esto significa que no puedo proporcionarles valores cuando realizo actualizaciones o inserciones utilizando Linq a SQL. Tampoco quiero que sean IsDbGenerated si esto significa que tengo que modificar manualmente el código generado por Linq a SQL.

EDITAR: La respuesta parece ser que esto es una limitación en el actual Linq a SQL.

14
Duplicado: stackoverflow.com/q/1120858/11683 (no se vota para cerrar, ambos son igualmente útiles).
agregado el autor GSerg, fuente

4 Respuestas

Las clases generadas de Linq-To-Sql no recogen los Constriants de valor predeterminado.

Tal vez en el futuro, pero el problema es que las limitaciones no son siempre valores simples, sino que también pueden ser funciones escalares como GetDate() , por lo que linq tendría que saber cómo traducirlas. En resumen, ni siquiera lo intenta. También es un tipo de cosas muy específicas de la base de datos.

  • Podrías escribir un generador de código para crear clases parciales de entidad donde puedes extraer el valor constriant predeterminado.
  • Alternativamente, el código de la capa de su empresa podría establecer los valores predeterminados en los constructores desde un archivo xml, y todo lo que necesita hacer es mantener el archivo xml actualizado.
  • En lugar de hacer el trabajo en constructores, puede emular SQL y agregar valores predeterminados inspeccionando el conjunto de cambios antes de enviar cambios a la base de datos.

The issue you are having is described at length in CodeProject - Setting Default Values for LINQ Bound Data

5
agregado
"linq de alguna manera tendría que saber cómo traducir esos" - ¿por qué? Simplemente podría permitir que no se pase nada en crear/actualizar, y leerlos luego. Así es como funcionan los campos IsDbGenerated, a excepción de su estado de solo lectura en el lado de Linq.
agregado el autor bzlm, fuente
Claro, podría permitirlo, pero no es así. IsDbGenerated es solo para columnas clave en este momento. El "linq de alguna manera ..." es solo mi opinión sobre por qué este puede ser el caso.
agregado el autor Robert Paulson, fuente
parece que IsDbGenerated ahora también está disponible para columnas que no son clave.
agregado el autor Make it useful Keep it simple, fuente

Me encontré con el mismo problema, bzlm, y llegué a la misma conclusión. Simplemente no hay una buena manera de obtener campos que no admiten nulos con valores predeterminados asignados por DB que funcionen con Linq To Sql.

El trabajo con el que me he ido es agregar un método SetDefaults() muy similar al que Robert Paulson vinculó en CodeProject y llamarlo en el constructor predeterminado de la clase base de mi entidad de tabla. Funciona bien para mí, porque el 95% de las veces, estoy configurando un 0, cadena vacía o getdate ().

3
agregado
Sí, lo mismo aquí. ¡Gracias!
agregado el autor bzlm, fuente

This means that when I make inserts using Linq to SQL, the following will happen:

  1. The bit will be sent as 0, overriding the default value. Right? - Correct
  2. The smalldatetime will be sent as an uninitialized System.DateTime, producing an error in SQL server since it doesn't fall with the SQL Server smalldatetime range. Right? - What is sent is DateTime.MinValue
  3. The IsDbGenerated int will not be sent; the DB will generate a value which Linq to SQL will then read back. - If DB generated is set then the value is created by the database, if not then Linq expects the user to set the value.

Su mejor opción es establecerlos en el constructor del objeto, o en los campos privados, si no está usando propiedades automáticas.

2
agregado
Es posible pero no puedes cambiarlos después del hecho. Si desea poder cambiarlos, debe crearlos en el constructor.
agregado el autor David Basarab, fuente
No use el constructor, hay un método parcial especial llamado OnCreate para esto. Vea esta pregunta: stackoverflow.com/questions/82409/…
agregado el autor Sam, fuente
Parece que está diciendo que los valores predeterminados en los campos en los valores de SQL Server NO son posibles de combinar con Linq To SQL. ¿Es esto correcto?
agregado el autor bzlm, fuente
Lo siento, no entiendo. ¿Que es posible? ¿Y qué no se puede cambiar después de qué hecho? ¿Es posible hacer que Linq To SQL realice una inserción y tenga los "valores predeterminados" especificados en la base de datos utilizada?
agregado el autor bzlm, fuente
En realidad, está OnCreated. Las respuestas de Longhorn213 son muy confusas, y él/ella también ha editado mi pregunta original aparentemente sin ninguna razón. Solo ignóralo.
agregado el autor bzlm, fuente

Puede crear otro archivo para su contexto de datos (clase parcial) y luego usar los métodos parciales InsertYOURENTITY y UpdateYOURENTITY para inspeccionar sus propiedades y asignar los valores adecuados. Llame a ExecuteDynamicInsert o ExecuteDynamicUpdate después de su código y listo.

0
agregado
En realidad, la forma recomendada de hacerlo en el BLL es implementar el método parcial OnCreated() para la entidad, no el método que sugiera. Aún así, no es relevante para mi pregunta. Mi pregunta es acerca de los valores predeterminados en SQL Server, no en el BLL.
agregado el autor bzlm, fuente