2008-12-15 7 views
10

¿Hay alguna manera simple de acceder al DataContext en una clase de entidad linq2sql?Acceder al DataContext LINQ-2-SQL en la clase de entidad

Estoy tratando de crear algo como EntitySet pero no puedo entender cómo el EntitySet tiene acceso al contexto que creó el objeto de entidad en primer lugar.

Quiero tener una clase regular de entidad linq2sql para que la clase pueda acceder al DataContext que la creó. Sé que es posible porque cuando tienes una clase de entidad con una clave primaria, linq2sql te da la opción de cargar todos los hijos sin crear un nuevo DataContext.

Respuesta

3

Básicamente, no.

La clase EntitySet<T> tiene una propiedad interna Source que es asignada por el contexto de datos, que es cómo se obtiene a los datos bajo demanda. Sin embargo, no hay nada similar para las clases de datos en sí.

Sin embargo, creo que Entity Framework tiene mucho más acceso a esto, a costa de la jerarquía de objetos forzados.

A diferencia de Entity Framework, LINQ-to-SQL (por diseño) se puede utilizar con clases regulares que ignoran la persistencia, por lo que no supone que tenga acceso a este tipo de datos.

clase
1

una entidad no debería ser consciente del contexto de datos que es sólo un mapeo de la mesa, pero el contexto de datos tiene el conocimiento de todas las entidades y las propiedades de conexión

Usted es capaz de enlazar con el niño tabla a través de la clase de entidad padre debido a la relación de entidad y no a través del contexto de datos

La clase de contexto de datos se usará al final donde se consumen las entidades, no veo la necesidad de que las entidades estén al tanto del contexto,

Si puede ver el escenario específico, podemos intentarlo otro enfoque.

+1

tengo el mismo problema y aunque entiendo su argumento para esto (créame, estoy a favor de ello), tengo una necesidad en el mundo real para esto. En algunas de nuestras clases parciales de entidad, agregamos algunas propiedades que deben consultar la base de datos en función de una propiedad de su entidad, para obtener una colección de otras entidades, que no están asociadas directamente en el servidor SQL. Esto es realmente feo porque estamos creando un nuevo contexto de datos al llamar estas propiedades (algunas de ellas en un bucle). –

0

Sé exactamente lo que quiere decir. Se supone que debemos hacer nuestros cálculos/validación dentro de la clase parcial de la entidad, pero si la entidad no tiene acceso al contexto de datos, ¿cuánto podemos hacer? Por ejemplo, en mi objeto SalesOrder, cada vez que se cambia la dirección "Enviar a", el SalesOrder necesita consultar la base de datos para averiguar si un impuesto se aplica a ese estado/zip. He estado luchando contra esto por un tiempo, pero hoy me derrumbé y fui con el método feo, pero hasta ahora todo bien. Esencialmente, todo lo que hago es crear una propiedad de "Contexto" en mi clase parcial y configurarla con el contexto de datos cada vez que se crea una entidad.

Partial Class SalesOrder 
    Private moContext As L2S_SalesOrdersDataContext 

    Friend Property Context() As L2S_SalesOrdersDataContext 
     Get 
      Return moContext 
     End Get 
     Set(ByVal value As L2S_SalesOrdersDataContext) 
      moContext = value 
     End Set 
    End Property 
... 

YMMV, especialmente si está desconectando sus entidades.

0

Básicamente, puede hacer esto con un poco de hackeo. DataContext adjunta un StandardChangeTracker a su entidad:

 
      DataContext context = null; 
      object changeTracker = (from i in o1.GetInvocationList() where i.Target.GetType().FullName == "System.Data.Linq.ChangeTracker+StandardChangeTracker" select i.Target).FirstOrDefault(); 
      if (changeTracker != null) // DataCOntext tracks our changes through StandardChangeTracker 
      { 
       object services = Reflector.GetFieldValue(changeTracker, "services"); 
       context = (DataContext)Reflector.GetFieldValue(services, "context"); 
      } 

Dónde Reflector.GetFieldValue es igual a

 
     public static object GetFieldValue(object instance, string propertyName) 
     { 
      return instance.GetType().GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance); 
     } 
6

yo sólo he tenido que hacer exactamente lo mismo.Aquí está mi solución (aunque probablemente no sea el mejor enfoque, pero al menos es bastante elegante):

En primer lugar, cree una interfaz para implementar todas las entidades que hereda de INotifyPropertyChanging. Esto se usa para conectar algunos métodos de extensión y mantener nuestra implementación bien separada. En mi caso, la interfaz se llama ISandboxObject:

public interface ISandboxObject : INotifyPropertyChanging 
{ 
    // This is just a marker interface for Extension Methods 
} 

a continuación, crear una nueva clase estática para contener un método de extensión para obtener el DataContext. Esto se logra al buscar un controlador de eventos en el rastreador de cambios LINQ adjunto al evento INotifyPropertyChanging.PropertyChanging. Una vez que hemos encontrado el cambio de seguimiento, podemos obtener el DataContext de allí:

/// <summary> 
    /// Obtain the DataContext providing this entity 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    public static DataContext GetContext(this ISandboxObject obj) 
    { 
     FieldInfo fEvent = obj.GetType().GetField("PropertyChanging", BindingFlags.NonPublic | BindingFlags.Instance); 
     MulticastDelegate dEvent = (MulticastDelegate)fEvent.GetValue(obj); 
     Delegate[] onChangingHandlers = dEvent.GetInvocationList(); 

     // Obtain the ChangeTracker 
     foreach (Delegate handler in onChangingHandlers) 
     { 
      if (handler.Target.GetType().Name == "StandardChangeTracker") 
      { 
       // Obtain the 'services' private field of the 'tracker' 
       object tracker = handler.Target; 
       object services = tracker.GetType().GetField("services", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(tracker); 

       // Get the Context 
       DataContext context = services.GetType().GetProperty("Context").GetValue(services, null) as DataContext; 
       return context; 
      } 
     } 

     // Not found 
     throw new Exception("Error reflecting object"); 
    } 

Ahora usted tienen un método de extensión agradable que le proporcionará un DataContext de cualquier objeto que implementa ISandboxObject. Por favor, ponga un poco más de comprobación de errores en esto antes de usarlo con ira.

Cuestiones relacionadas