2010-05-20 11 views
21

puedo actualizar el registro de empleado como se da en la función por debajo o por qué tengo que hacer una consulta de la colección empleado primero y luego actualizar los datos?forma más eficiente para actualizar con LINQ to SQL

public int updateEmployee(App3_EMPLOYEE employee) 
    { 
     DBContextDataContext db = new DBContextDataContext(); 
     db.App3_EMPLOYEEs.Attach(employee); 
     db.SubmitChanges(); 
     return employee.PKEY; 
    } 

¿O tengo que hacer lo siguiente?

public int updateEmployee(App3_EMPLOYEE employee) 
{ 
    DBContextDataContext db = new DBContextDataContext(); 
    App3_EMPLOYEE emp = db.App3_EMPLOYEEs.Single(e => e.PKEY == employee.PKEY); 
    db.App3_EMPLOYEEs.Attach(employee,emp); 
    db.SubmitChanges(); 
    return employee.PKEY; 
} 

Pero no quiero usar la segunda opción. ¿Hay alguna forma eficiente de actualizar los datos?

estoy recibiendo este error mediante el uso de dos maneras: Se ha hecho

Un intento de Adjuntar o Agregar una entidad que no es nuevo, tal vez después de haber sido cargado desde otro DataContext. Esto no es compatible.

+0

en el segundo método adjunta entidad al contexto, porque ya está lleno de él. Simplemente llame a SubmitChanges() – Sharique

Respuesta

9

encuentro siguiente trabajo en torno a este problema:

1) traer y entidad de actualización (voy a utilizar esta forma porque es bien para mí)

public int updateEmployee(App3_EMPLOYEE employee) 
{ 
    AppEmployeeDataContext db = new AppEmployeeDataContext(); 
    App3_EMPLOYEE emp = db.App3_EMPLOYEEs.Single(e => e.PKEY == employee.PKEY); 
    emp.FIRSTNAME = employee.FIRSTNAME;//copy property one by one 
    db.SubmitChanges(); 
    return employee.PKEY; 
} 

2) desactivar ObjectTrackingEnabled de la siguiente manera

// but in this case lazy loading is not supported 


    public AppEmployeeDataContext() : 
        base(global::LinqLibrary.Properties.Settings.Default.AppConnect3DBConnectionString, mappingSource) 
      { 
       this.ObjectTrackingEnabled = false; 
       OnCreated(); 
      } 

3) Separar todos los objetos relacionados

partial class App3_EMPLOYEE 
{ 
    public void Detach() 
    { 
     this._APP3_EMPLOYEE_EXTs = default(EntityRef<APP3_EMPLOYEE_EXT>); 
    } 
} 

public int updateEmployee(App3_EMPLOYEE employee) 
{ 
    AppEmployeeDataContext db = new AppEmployeeDataContext(); 
    employee.Detach(); 
    db.App3_EMPLOYEEs.Attach(employee,true); 
    db.SubmitChanges(); 
    return employee.PKEY; 
} 

4) utilizan Sello de tiempo en la columna

http://www.west-wind.com/weblog/posts/135659.aspx 

5) Crear procedimiento almacenado para actualizar sus datos y llamarlo por db contexto

2

Hay una discusión sobre este tema here at MSDN s recomiendan el uso de un campo IsVersion y el método attach

+0

gracias por la información ... pero ya lo he visto –

3

no se puede adjuntar una entidad modificado a un DataContext cuando no hay ninguna columna rowversion. En su lugar, puede almacenar la entidad original en su aplicación siempre que mantenga una copia para los cambios de datos. Luego, cuando los cambios necesitan ser salvados podría adjuntar entidad original a un DataContext, cambiar sus valores para que coincida con los valores de entidad modificados y enviar los cambios.

Aquí se muestra un ejemplo:

public int updateEmployee(App3_EMPLOYEE employee, App3_EMPLOYEE originalEmployee) 
{ 
    DBContextDataContext db = new DBContextDataContext(); 
    db.App3_EMPLOYEEs.Attach(originalEmployee); 

    // TODO: Copy values from employee to original employee 

    db.SubmitChanges(); 
    return employee.PKEY; 
} 

Actualización:

Hay una tabla en la base de datos con las columnas ID, Nombre, Notas

// fetch an employee which will not be changed in the application 
Employee original; 
using(var db = new TestDbDataContext()) 
{ 
    original = db.Employees.First(e => e.ID == 2); 
} 

// create an instance to work with 
var modified = new Employee {ID = original.ID, Name = original.Name, Notes = original.Notes}; 

// change some info 
modified.Notes = string.Format("new notes as of {0}", DateTime.Now.ToShortTimeString()); 
// update 
using(var db = new TestDbDataContext()) 
{ 
    db.Employees.Attach(original); 
    original.Notes = modified.Notes; 
    db.SubmitChanges(); 
} 
+0

sin conseguirlo, puede enviarme algún enlace o ejemplo de eso –

+0

Voy a agregar un código de prueba para demostrar todo el escenario –

+0

en este momento estoy usando el Lo mismo para hacer frente a los datos modificados al original –

2

Puede adjuntar una ataduras entidad modificada, al usar esta sobrecarga:

db.App3_EMPLOYEEs.Attach(employee, true);//Attach as modfieied 

Tenga en cuenta que para que esto funcione es necesario en la tabla de una columna "Versión" de tipo "marca de tiempo"

0

Ésta es una función en mi clase de repositorio que utilizo para actualizar las entidades

protected void Attach(TEntity entity) 
{ 
    try 
    { 
     _dataContext.GetTable<TEntity>().Attach(entity); 
     _dataContext.Refresh(RefreshMode.KeepCurrentValues, entity); 
    } 
    catch (DuplicateKeyException ex) //Data context knows about this entity so just update values 
    { 
     _dataContext.Refresh(RefreshMode.KeepCurrentValues, entity); 
    } 
} 

donde TEntity es su clase DB y dependiendo de la configuración que es posible que quieran hacer

_dataContext.Attach(entity); 
0

el uso de este método para la actualización se extienden todas las propiedades que son atributos de columna:

public static void SaveToOriginal<T>(this T original, T actual) 
    { 
     foreach (var prop in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance) 
      .Where(info => info.GetCustomAttribute<System.Data.Linq.Mapping.ColumnAttribute>() != null)) 
     { 
      prop.SetValue(original, prop.GetValue(actual)); 
     } 
    } 

Quiero decir, primero recuperas el original de la base de datos, usa el método para mapear todos los atributos de las columnas del nuevo elemento al original, y al final haz un envío. Espero que esto ayude.