Pergunta

Se eu tiver os objetos LINQ:

public class SampleDataContext : DataContext {
    public Table<Customer> Customers { get { return this.GetTable<Customer>(); } }
    public SampleDataContext( string connectionString ) : base( connectionString ) { }
}

[Table( Name="dbo.tblCustomers" )]
public class Customer {
    private Guid? customerID;
    [Column( Storage="customerID", DbType="uniqueidentifier NOT NULL", IsPrimaryKey=true )]
    public Guid? CustomerID {
        get { return this.customerID; }
        set { this.customerID = value; }
    }

    private string customerName;
    [Column( Storage = "customerName", DbType = "nvarchar(255) NOT NULL" )]
    public string CustomerName {
        get { return this.customerName; }
        set { this.customerName = value; }
    }
}

e em outro lugar no aplicativo:

public static void DoSomethingWithCustomer( Customer customer ) {
    // some operations
    // now, I want save changes to the database
}

Como posso obter instância de DataContext que controla as alterações do objeto "cliente"?

Editar: Por que eu não quero passar o DataContext no método

.

1) Passando sempre 2 objetos em vez de 1 é o padrão de "feio" para a aplicação inteira.

  • Métodos precisará próximo parâmetro para cada objeto de negócios.
  • Coleção irá necessidades alterada de "Lista" para "Lista>".

Ambos os pontos serão mais difíceis de manter - desenvolvedor deve cada vez define a instância correta do DataContext (fácil de criar um bug), apesar das DataContext saber que o objeto concreto é (ou não) anexado a outro DataContext

2) Eu quero (versão atual do uso do aplicativo lo) processo de "qualquer" lógica de negócios na coleção de objetos que vieram de diferentes "lugares" (janelas flutuantes por drag & drop, por exemplo).

Currentyl usamos costume digitado DataSets, para que informações sobre alterações estão nas linhas de dados (DataRow = objeto de negócios) e não foi problema para obtê-lo, ou criar um clone e depois salvá-lo no banco de dados.

Foi útil?

Solução

Kevin - eu sinto sua dor ... quando você está construindo a lógica de negócios em torno de seus objetos de negócios, há momentos em que você simplesmente Have para ter acesso ao DataContext ao qual pertence um objeto, uma vez não conhecendo as menas DataContext ter de colocar seu código em lugares que reduzem a capacidade de manutenção do seu código.

Eu escrevi o seguinte código (VB, eu tenho medo), que apresenta uma propriedade de contexto que pode ser colocado em um objeto de dados e, em seguida, usado para retornar o DataContext (se houver) que o objeto está anexado.

Private Const StandardChangeTrackerName As String = "System.Data.Linq.ChangeTracker+StandardChangeTracker"

Private _context As DataClasses1DataContext
Public Property Context() As DataClasses1DataContext
    Get
        Dim hasContext As Boolean = False
        Dim myType As Type = Me.GetType()
        Dim propertyChangingField As FieldInfo = myType.GetField("PropertyChangingEvent", BindingFlags.NonPublic Or BindingFlags.Instance)
        Dim propertyChangingDelegate As PropertyChangingEventHandler = propertyChangingField.GetValue(Me)
        Dim delegateType As Type = Nothing

        For Each thisDelegate In propertyChangingDelegate.GetInvocationList()
            delegateType = thisDelegate.Target.GetType()
            If delegateType.FullName.Equals(StandardChangeTrackerName) Then
                propertyChangingDelegate = thisDelegate
                hasContext = True
                Exit For
            End If
        Next

        If hasContext Then
            Dim targetField = propertyChangingDelegate.Target
            Dim servicesField As FieldInfo = targetField.GetType().GetField("services", BindingFlags.NonPublic Or BindingFlags.Instance)
            If servicesField IsNot Nothing Then

                Dim servicesObject = servicesField.GetValue(targetField)

                Dim contextField As FieldInfo = servicesObject.GetType.GetField("context", BindingFlags.NonPublic Or BindingFlags.Instance)

                _context = contextField.GetValue(servicesObject)

            End If
        End If

        Return _context
    End Get
    Set(ByVal value As DataClasses1DataContext)

        _context = value

    End Set

End Property

Aqui está uma versão C #:

public DataContext GetMyDataContext()
{
    // Find the StandardChangeTracker listening to property changes on this object.
    // If no StandardChangeTracker is listening, then this object is probably not
    // attached to a data context.
    var eventField = this.GetType().GetField("PropertyChangingEvent", BindingFlags.NonPublic | BindingFlags.Instance);
    var eventDelegate = eventField.GetValue(this) as Delegate;
    if (eventDelegate == null)
        return null;
    eventDelegate = eventDelegate.GetInvocationList().FirstOrDefault(
        del => del.Target.GetType().FullName == "System.Data.Linq.ChangeTracker+StandardChangeTracker");
    if (eventDelegate == null)
        return null;

    // Dig through the objects to get the underlying DataContext.
    // If the following fails, then there was most likely an internal change
    // to the LINQ-to-SQL framework classes.
    var targetField = eventDelegate.Target;
    var servicesField = targetField.GetType().GetField("services", BindingFlags.NonPublic | BindingFlags.Instance);
    var servicesObject = servicesField.GetValue(targetField);
    var contextField = servicesObject.GetType().GetField("context", BindingFlags.NonPublic | BindingFlags.Instance);
    return (DataContext)contextField.GetValue(servicesObject);
}

Tome o cuidado de observar que o objeto só pode localizá-lo de DataContext se ele estiver ligado ao contexto com ChangeTracking ligado. Esta propriedade se baseia no fato de que o DataContext subscreveu evento OnPropertyChanging do objeto para a monitorizar as alterações ao longo do tempo de vida do objeto.

Se isso foi útil, por favor, up-voto este post.

Para obter mais informações sobre como usar a reflexão para encontrar manipuladores de eventos: http: //weblogs.asp. net / avnerk / Arquivo / 2007/03/29 / refletindo-over-an-event.aspx http://www.bobpowell.net/eventsubscribers.htm

Outras dicas

Parte da diversão de POCO é que você não pode ter certeza que o objeto sabe , que é o acompanhamento dele. Se o objeto tem propriedades / lazy-carregamento de dados de reconhecimento, então você pode ser capaz de traçar o contexto através da reflexão, mas, na realidade, isso seria uma bagunça. Seria muito mais limpo para simplesmente passar o contexto de dados para o código que precisa.

A coisa mais simples a fazer é passar o DataContext em seu método.

No entanto, você também pode considerar mudar seu projeto de modo que você siga a regra de que "um único método deve ter apenas um propósito", caso em que você não gostaria de "Save" no mesmo método que você "Modificar ".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top