2008-12-22 11 views
6

He publicado este question ayer por la tarde, lo que me ha llevado a descubrir un gran problema!Linq-to-Sql SubmitChanges no actualiza campos ... ¿por qué?

Tengo una columna decimal en mi base de datos llamada Unidades, cada vez que configuro el valor de la columna como NO CERO, y SubmitCambia las actualizaciones de columna con el nuevo valor. Si intento establecer el valor de la columna en CERO, el SubmitChanges no actualiza la columna.

data.Units = this.ReadProperty<decimal>(UnitsProperty); 
data.UnitPrice = this.ReadProperty<decimal>(UnitPriceProperty); 
data.Price = this.ReadProperty<decimal>(PriceProperty); 

que he tomado un vistazo al registro de DataContext y puedo ver que el campo con el valor cero no está incluido en la consulta. Incluso si trato de codificar el cambio, Linq lo ignora.

data.Units = 0; 
data.UnitPrice = 0; 
data.Price = 0; 

¡No hace falta decir que esto me está matando! ¿Alguna idea de por qué sucede esto?

Solución

me di cuenta de mi problema con la ayuda de la comunidad SO. Mi problema fue causado por el hecho de que cuando creé mi entidad para adjuntar, el valor predeterminado de la columna se estableció en cero, por lo que cuando intentó asignar el valor a cero ... LinqToSql dice "hey ... nada cambió, por lo No estoy actualizando el valor.

Lo que estoy haciendo ahora ... sólo para que sea trabajo es la siguiente:

ctx.DataContext.InvoiceItems.Attach(data, true); 

que parece obligar a todos los valores de escribir ellos mismos a la base de datos. Esto funciona por ahora.

+0

¿Alguno de los métodos parciales en su clase como OnCreated() o OnChanged() ha causado interferencia? ¿Has triplicado el control de tu modelo? –

+0

@Dave pregunta tonta ... pero ¿qué quieres decir con triple tripa? – mattruma

+0

Quiero decir que es temprano y todavía no he tomado mi café. ;-) Es decir, ¿has verificado dos veces la definición de tu archivo dbml (tipos de datos, anulables, relaciones) contra tu db? –

Respuesta

2

Descubrí mi problema con la ayuda de la comunidad SO. Mi problema fue causado por el hecho de que cuando creé mi entidad para adjuntar, el valor predeterminado de la columna se estableció en cero, por lo que cuando intentó asignar el valor a cero ... LinqToSql dice "hey ... nada cambió, por lo No estoy actualizando el valor.

Lo que estoy haciendo ahora ...sólo para hacer que funcione es la siguiente:

ctx.DataContext.InvoiceItems.Attach(data, true); 

que parece forzar todos los valores de escribir ellos mismos a la base de datos. Esto funciona por ahora.

3

He intentado reproducir esto con el siguiente código, pero para mí funciona.

using (DataClasses1DataContext ctx = new DataClasses1DataContext()) 
{ 
    var obj = ctx.DecimalColumnTables.First(); 
    Debug.Assert(obj.B != 0); 
    obj.B = 0; 
    ctx.SubmitChanges(); 
} 

Así que creo que debe haber algo especial en su dominio que cause esto. Te sugiero que crees una reproducción simple con tu modelo de dominio y veas qué sucede.

LINQ to SQL ignora las actualizaciones del valor actual, por lo que si el campo ya era cero, es posible que no vea ninguna actualización.

Apagado: El OR/M que utiliza es LINQ to SQL. LINQ es el nombre de la capacidad de consulta en .NET, pero LINQ no define ni implementa ninguna lógica de actualización. Entonces, el problema se relaciona con LINQ to SQL, no LINQ.

+0

¡Gracias! Voy a verificar esto! – mattruma

+0

Tenías razón en @Gaspar Nagy ... Linq a Sql estaba ignorando el cambio. – mattruma

2

Pregunta obvia, pero ¿está seguro de que la columna está asignada en el archivo dbml/mapping?

Además, ¿se trata de una columna calculada? (es decir, precio = > unidades * precio por unidad)

2

Algunos más información ... me di cuenta de mi problema ... es más bien una falta de comprensión sobre LinqToSql ... donde yo estoy haciendo:

private void Child_Update(Invoice parent) 
{ 
     using (var ctx = Csla.Data.ContextManager 
      .GetManager(Database.ApplicationConnection, false)) 
     { 
      var data = new Gimli.Data.InvoiceItem() 
      { 
       InvoiceItemId = ReadProperty(InvoiceItemIdProperty) 
      }; 

      ctx.DataContext.InvoiceItems.Attach(data); 

      if (this.IsSelfDirty) 
      { 
       // Update properties 
      } 
    } 
} 

pensé que esto sería cargar los valores originales ... lo que sucede es que crea un nuevo objeto con valores predeterminados ... valores vacíos, como 0 para decimales, Guid.Empty para uniqueidentifiers, etc.

Por lo tanto, cuando actualiza las propiedades, ve las unidades como 0 y lo pone a cero. Bueno, LinqToSql no reconoce esto como un cambio por lo que no actualiza el campo. Así que lo que he tenido que hacer es lo siguiente:

ctx.DataContext.InvoiceItems.Attach(data, true); 

Ahora todas las modificaciones se generan en la instrucción de actualización si realmente hay un cambio o no. Esto funciona ... parece un poco hackish!

0

Tuve este problema y todas las sugerencias que había visto no se aplicaron ni funcionaron.

¡Pero descubrí que había cometido un error muy simple!

Al actualizar la propiedad, en realidad estaba llamando a un método Set personalizado (porque había otras cosas que debían modificarse en respuesta a la propiedad principal en cuestión).

Después de horas de rascarse la cabeza, noté que mi método Set estaba actualizando el miembro privado, no la propiedad pública, es decir, this._Walking = value;

Todo lo que tenía que hacer era cambiar esto a esto. Caminar = valor; ¡y todo comenzó a funcionar!

1

La respuesta correcta es la mayor cantidad señaló a utilizar la sobrecarga especial de Fije el que acepta un parámetro booleano que se considere como modificado, (cometer el error de utilizar otro sobrecarga y simplemente no funcionará):

ctx.DataContext.InvoiceItems.Attach(data, true); 

Sin embargo, tenga en cuenta que aún puede necesitar tener una columna "Versión" en la tabla de tipo "marca de tiempo".

Cuestiones relacionadas