c# - studio - Linq-to-Sql SubmitChanges no actualiza campos... ¿por qué?
linq to sql vs entity framework (6)
Publiqué esta pregunta ayer por la tarde, lo que me llevó a descubrir un gran problema.
Tengo una columna decimal en mi base de datos llamada Unidades, cada vez que configuro el valor de la columna como NO CERO, y SubmitChanges 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);
He echado 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
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 ... solo para que funcione es lo siguiente:
ctx.DataContext.InvoiceItems.Attach(data, true);
Eso parece forzar a todos los valores a escribirse en la base de datos. Esto funciona por ahora.
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 ... solo para que funcione es lo siguiente:
ctx.DataContext.InvoiceItems.Attach(data, true);
Eso parece forzar a todos los valores a escribirse en la base de datos. Esto funciona por ahora.
Intenté 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();
}
Entonces creo que debe haber algo especial en tu 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.
Desactivado: 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.
Pregunta obvia, pero ¿está seguro de que la columna está asignada en el archivo dbml / mapping?
Además, ¿es una columna calculada? (es decir, precio => unidades * precio unitario)
Más información ... Descubrí mi problema ... es más una falta de comprensión sobre LinqToSql ... donde estoy:
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 cargaría 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.
Entonces, cuando actualiza las propiedades, ve las Unidades ya como 0 y lo pone a cero. Bueno, LinqToSql no reconoce esto como un cambio por lo que no actualiza el campo. Entonces, lo que he tenido que hacer es lo siguiente:
ctx.DataContext.InvoiceItems.Attach(data, true);
Ahora todas las modificaciones se generan en la declaración de actualización si realmente hay un cambio o no. Esto funciona ... parece un poco hackish!
Tuve este problema y todas las sugerencias que había visto no se aplicaron o 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!
La respuesta correcta es la que muchos señalaron para usar la sobrecarga especial de Attach que acepta un parámetro booleano para considerarlo como modificado (cometer el error de usar otra sobrecarga y simplemente no funcionará):
ctx.DataContext.InvoiceItems.Attach(data, true);
Sin embargo, tenga en cuenta que es posible que necesite tener una columna "Versión" en la tabla de tipo "marca de tiempo".