문제

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; }
    }
}

그리고 응용 프로그램의 다른 곳 :

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

"고객"객체의 변경 사항을 추적하는 DataContext 인스턴스를 어떻게 얻을 수 있습니까?

편집 : DataContext를 메소드로 전달하고 싶지 않은 이유.

1) 1 대신 항상 2 개의 객체를 통과하는 것은 전체 응용 프로그램의 "못생긴"패턴입니다.

  • 메소드는 모든 비즈니스 객체에 대한 다음 매개 변수가 필요합니다.
  • 컬렉션은 "목록"에서 "목록>"으로 변경해야합니다.

두 지점 모두 유지하기가 더 어려울 것입니다. 개발자는 매번 Datacontext가 콘크리트 객체가 다른 데이터 컨텍스트에 첨부되어 있음을 알고 있음에도 불구하고 Datacontext의 올바른 인스턴스 (버그를 쉽게 만들기 쉬운)를 설정해야합니다.

2) 나는 (현재의 응용 프로그램 사용) 프로세스를 원한다 "프로세스"프로세스 "다른"장소 "(예 : 드래그 앤 드롭에 의한 Windows 플로팅)에서 나온 객체 모음에 대한"비즈니스 로직 ".

currentyl 우리는 사용자 정의 입력 데이터 세트를 사용하므로 변경 사항에 대한 정보는 데이터 행 (Datarow = Business Object)에 있으며 복제를 얻거나 클론을 만들고 데이터베이스에 저장하는 데 문제가되지 않았습니다.

도움이 되었습니까?

해결책

KEVIN- 고통을 느낍니다 ... 비즈니스 대상 주위에 비즈니스 로직을 구축 할 때 간단한 시간이 있습니다. 가지다 Datacontext 메나를 알지 못하기 때문에 코드가 코드의 유지 관리 가능성을 줄이는 위치에 코드를 넣어야한다는 것을 알지 못하기 때문에 객체가 속한 DataContext에 액세스하려면.

다음 코드 (VB, I 'm Feak)를 작성했습니다.이 코드는 데이터 객체에 배치 할 수있는 컨텍스트 속성을 제시 한 다음 객체가 첨부 된 데이터 컨텍스트 (있는 경우)를 반환하는 데 사용했습니다.

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

다음은 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);
}

객체는 현재 Changetracking이 켜진 상태에서 컨텍스트에 첨부 된 경우에만 데이터 콘텍스트 만 찾을 수 있습니다. 이 속성은 Datacontext가 객체의 수명 동안 변경 사항을 모니터링하기 위해 객체의 onpropertychanging 이벤트에 가입했다는 사실에 의존합니다.

이것이 도움이된다면이 게시물을 발표하십시오.

반사를 사용하여 이벤트 핸들러를 찾으려면 :http://weblogs.asp.net/avnerk/archive/2007/03/29/reflecting-over-an-event.aspx http://www.bobpowell.net/eventsubscriber.htm

다른 팁

재미의 일부 포코 객체를 확신 할 수 없다는 것입니다 알고 있습니다 그를 추적하는 사람. 객체에 데이터 인식 / 게으른로드 속성이 있으면 ~할 것 같다 반사를 통해 컨텍스트를 추적 할 수 있지만 실제로는 혼란이 될 것입니다. 데이터 텍스트를 필요한 코드로 간단히 전달하는 것이 훨씬 더 깨끗합니다.

가장 간단한 일은 데이터 컨텍스트를 메소드에 전달하는 것입니다.

그러나 디자인 변경을 고려하여 "단일 메소드가 하나의 목적 만 있어야한다"는 규칙을 준수 할 수 있습니다.이 경우 "수정"과 동일한 방법으로 "저장"하고 싶지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top