2009-05-12 8 views
8

¿Hay alguna manera de determinar si un objeto LINQ no se ha insertado aún en la base de datos (nuevo) o se ha modificado desde la última actualización (sucia)? Planeo encuadernar mi UI a objetos LINQ (usando WPF) y necesito que se comporte de manera diferente dependiendo de si el objeto ya está en la base de datos.LINQ to SQL - Seguimiento de objetos nuevos/sucios

MyDataContext context = new MyDataContext(); 
MyObject obj; 
if (new Random().NextDouble() > .5) 
    obj = new MyObject(); 
else 
    obj = context.MyObjects.First(); 
// How can I distinguish these two cases? 

La única solución simple que puedo pensar es para establecer la clave primaria de nuevos registros a un valor negativo (mis PK son un campo de identidad y por lo tanto pueden ajustar a un número entero positivo en INSERT). Esto solo funcionará para detectar nuevos registros. También requiere PK de identidad y requiere el control del código que crea el nuevo objeto.

¿Hay una mejor manera de hacerlo? Parece que LINQ debe realizar un seguimiento interno del estado de estos objetos para que pueda saber qué hacer en context.SubmitChanges(). ¿Hay alguna forma de acceder a ese "estado del objeto"?

aclaración Aparentemente mi pregunta inicial fue confusa. No estoy buscando una forma de insertar o actualizar registros. Estoy buscando un camino, dado cualquier objeto LINQ, para determinar si ese objeto no se ha insertado (nuevo) o si se ha cambiado desde su última actualización (sucio).

Respuesta

14

ChangeSet changes = context.GetChangeSet();

Si changes.Inserts.Contains (yourObject), entonces es nuevo y se insertará cuando SubmitChanges se llama

Si changes.Updates.Contains (yourObject), que ya está en la base de datos, y se actualizará SubmitChanges()

1

El objeto DataContext hace un seguimiento interno de los cambios a los datos para que pueda optimizar las consultas SQL generadas cuando llama a SubmitChanges().

Si desea insertar nuevos objetos a la base de datos, en lugar de actualizar los objetos existentes, se debe hacer algo como:

MyDataContext context = new MyDataContext(); 
MyObject obj; 
if (new Random().NextDouble() > .5) 
{ 
    obj = new MyObject(); 
    context.MyObjects.InsertAllOnSubmit(obj); 
} 
else 
    obj = context.MyObjects.First(); 

Ahora cuando se llama SubmitChanges(), que va a generar tanto un INSERT y una ACTUALIZAR si es necesario. Según la rapidez con la que necesite una clave principal en su nuevo objeto, puede enviarla de inmediato para enviar el objeto, vaciar el seguimiento de cambios y obtener su nueva clave principal.

+1

Esto no es exactamente lo que estoy buscando. Sé cómo insertar/actualizar usando LINQ. Lo que necesito es determinar el estado de cualquier objeto LINQ dado. –

2

puedo crear una clase parcial para cada objeto LINQ crea (Data Objects) y tienen cada objeto implementar la interfaz IDataObject

/// <summary> 
/// This interface is used to implement IsNew in all LINQ objects so a Generic Save method 
/// can be used. 
/// </summary> 
public interface IDataObject 
{ 

    #region Properties 


     #region IsNew 
     /// <summary> 
     /// Is this a new object 
     /// </summary> 
     bool IsNew 
     { 
      get; 
     } 
     #endregion 


    #endregion 

} 
#endregion 

En cada dato de objeto implemento la propiedad isNew para devolver cierto si PrimaryKey se ha establecido:

/// <summary> 
/// Is this a new object 
/// </summary> 
public bool IsNew 
{ 
    get 
    { 
     // initial value 
     bool isNew = (this.CustomerID > 0); 

     // return value 
     return isNew; 
    } 
} 

Luego, en mi DataContext que tire la ojbect para ser guardado como un IDataObject y si es nuevo me llaman InsertOnSubmit() antes de llamar SubmitChanges().

Puede que esta no sea la forma más sencilla, pero permite que todos los objetos se guarden genéricamente.

Tarda unos minutos para que cada tabla implemente la interfaz, pero permite llamar al método Generic Save().

0

Hay interfaces INotifyPropertyChanging e INotifyPropertyChanged que tienen métodos específicos para activarse en la inserción que le permite saber si el objeto se ensucia. Si usa SQLMetal, lo hace automáticamente. si escribe sus propias clases de entidades, usted mismo debe escribir estas herramientas de plomería manualmente. Pero no estoy seguro de si esta solución es adecuada desde el punto de vista de escalabilidad. No lo he probado. Parece que podría tener problemas ya que dispara un evento en la máquina que realiza la inserción.