http://msdn.microsoft.com/ko-kr/library/bb546187.aspx

웹서비스를 통한 엔티티모델은 서로 연결이 되있지 않기 때문에 업데이트라든지 삭제,추가는 조금 다른방법으로 구현필요

 

Customers 또는 Orders와 같은 엔터티 개체를 네트워크상의 클라이언트로 serialize하면 해당 엔터티가 원래 데이터 컨텍스트에서 분리됩니다.

 

데이터 컨텍스트에서는 분리된 엔터티 개체에 대해서는 변경 내용이나 다른 개체와의 관계를 더 이상 추적하지 않습니다.

이러한 특징은 클라이언트에서 데이터를 읽기만 하는 경우에는 문제가 되지 않습니다. 또한 클라이언트가 데이터베이스에 새 행을 추가할 수 있게 하는 것도 비교적 간단합니다. 그러나 응용 프로그램에서 클라이언트가 데이터를 업데이트하거나

삭제해야 하는 경우에는 DataContext..::.SubmitChanges를 호출하기 전에 새 데이터 컨텍스트에 엔터티를 연결해야 합니다. 또한 원래 값을 기준으로 낙관적 동시성 검사를 사용하는 경우에는 어떤 방법으로든 데이터베이스에 원래 엔터티와 수정된 엔터티를 모두 제공해야 합니다.

Attach 메서드는 분리된 엔터티를 새 데이터 컨텍스트에 연결하기 위해 제공됩니다.

데이터 삭제

데이터베이스에서 기존 개체를 삭제할 경우 프레젠테이션 계층에서는 중간 계층 인터페이스에서 관련 메서드를 호출하고, 삭제할 개체의 원래 값이 포함된 복사본을 전달합니다.

삭제 작업에는 낙관적 동시성 검사가 사용되기 때문에 삭제할 개체를 새 데이터 컨텍스트에 먼저 연결해야 합니다. 이 예제에서는 Boolean 매개 변수를 false로 설정하여 개체에 타임스탬프(RowVersion)가 없음을 나타냅니다. 그러나 데이터베이스 테이블에서 각 레코드에 대해 타임스탬프를 생성하는 경우 클라이언트측에서는 동시성 검사가 훨씬 간단해집니다. 즉, 원래 개체 또는 수정된 개체 중 하나를 전달하고 Boolean 매개 변수를 true로 설정하기만 하면 됩니다. 그러나 어떤 경우든 중간 계층에서는 일반적으로 ChangeConflictException을 catch해야 합니다. 낙관적 동시성 충돌을 처리하는 방법에 대한 자세한 내용은 낙관적 동시성 개요(LINQ to SQL)를 참조하십시오.

연결된 테이블에 외래 키 제약 조건이 있는 엔터티를 삭제할 경우에는 해당 EntitySet<(Of <(TEntity>)>) 컬렉션에 있는 모든 개체를 먼저 삭제해야 합니다.

// Attach is necessary for deletes.
public void DeleteOrder(Order order)
{
    NorthwindClasses1DataContext db = new NorthwindClasses1DataContext(connectionString);

    db.Orders.Attach(order, false);
    // This will throw an exception if the order has order details.
    db.Orders.DeleteOnSubmit(order);
    try
    {
        // ConflictMode is an optional parameter.
        db.SubmitChanges(ConflictMode.ContinueOnConflict);
    }
    catch (ChangeConflictException e)
    {
       // Get conflict information, and take actions
       // that are appropriate for your application.
       // See MSDN Article How to: Manage Change Conflicts (LINQ to SQL).
    }
}

 

데이터 업데이트

LINQ to SQL은 낙관적 동시성이 사용되는 다음과 같은 시나리오에서 업데이트를 지원합니다.

  • 타임스탬프 또는 RowVersion 번호를 기반으로 하는 낙관적 동시성

  • 엔터티 속성 하위 집합의 원래 값을 기반으로 하는 낙관적 동시성

  • 원래 엔터티와 수정된 엔터티 모두를 기반으로 하는 낙관적 동시성

Customer 및 Customer와 연결된 Order 개체의 컬렉션과 같이 엔터티와 해당 관계에 대해 업데이트나 삭제 작업을 수행할 수도 있습니다. 클라이언트에서 엔터티 개체의 그래프와 해당 자식(EntitySet) 컬렉션을 수정할 경우 낙관적 동시성 검사에 원래 값이 필요하면 클라이언트에서는 각 엔터티와 EntitySet<(Of <(TEntity>)>) 개체의 원래 값을 제공해야 합니다. 클라이언트에서 한 번의 메서드 호출로 관련된 업데이트, 삭제 및 삽입을 수행하려면 각 엔터티에 대해 수행할 작업 유형을 메서드 안에 지정할 수 있어야 합니다. 그런 다음 SubmitChanges를 호출하기 전에 중간 계층에서 적절한 Attach 메서드를 호출한 후 각 엔터티에 대해 InsertOnSubmit, DeleteAllOnSubmit 또는 InsertOnSubmit()()()(삽입의 경우 Attach가 필요하지 않음)을 호출해야 합니다. 업데이트를 시도하기 전에 원래 값을 가져오기 위한 방법으로 데이터베이스에서 데이터를 검색하지 마십시오.

낙관적 동시성에 대한 자세한 내용은 낙관적 동시성 개요(LINQ to SQL)를 참조하십시오. 낙관적 동시성 변경 충돌을 해결하는 방법에 대한 자세한 내용은 방법: 변경 내용 충돌 관리(LINQ to SQL)를 참조하십시오.

다음 예제에서는 각 시나리오를 보여 줍니다.

타임스탬프를 사용하는 낙관적 동시성

// Assume that "customer" has been sent by client.
// Attach with "true" to say this is a modified entity
// and it can be checked for optimistic concurrency because
//  it has a column that is marked with "RowVersion" attribute
db.Customers.Attach(customer, true)
try
{
    // Optional: Specify a ConflictMode value
    // in call to SubmitChanges.
    db.SubmitChanges();
}
catch(ChangeConflictException e)
{
    // Handle conflict based on options provided
    // See MSDN article How to: Manage Change Conflicts (LINQ to SQL).
}

 

원래 값의 하위 집합을 사용하는 낙관적 동시성
(이 경우 클라이언트는 serialize된 개체 전체 및 수정될 값을 반환합니다.)

public void UpdateProductInventory(Product p, short? unitsInStock, short? unitsOnOrder)
{
    using (NorthwindClasses1DataContext db = new NorthwindClasses1DataContext(connectionString))
    {
        // p is the original unmodified product
        // that was obtained from the database.
        // The client kept a copy and returns it now.
        db.Products.Attach(p, false);

        // Now that the original values are in the data context, apply the changes.
        p.UnitsInStock = unitsInStock;
        p.UnitsOnOrder = unitsOnOrder;
        try
        {
             // Optional: Specify a ConflictMode value
             // in call to SubmitChanges.
             db.SubmitChanges();
        }
        catch (ChangeConflictException e)
        {
            // Handle conflict based on provided options.
            // See MSDN article How to: Manage Change Conflicts
            // (LINQ to SQL).
        }
    }
}

 

전체 엔터티를 사용하는 낙관적 동시성

public void UpdateProductInfo(Product newProd, Product originalProd)
{
     using (NorthwindClasses1DataContext db = new
        NorthwindClasses1DataContext(connectionString))
     {
         db.Products.Attach(newProd, originalProd);
         try
         {
               // Optional: Specify a ConflictMode value
               // in call to SubmitChanges.
               db.SubmitChanges();
         }
        catch (ChangeConflictException e)
        {
            // Handle potential change conflict in whatever way
            // is appropriate for your application.
            // For more information, see the MSDN article
            // How to: Manage Change Conflicts (LINQ to SQL)/
        }
    }
}

 

 

필요한 엔터티 멤버

앞에서 설명한 것처럼 Attach 메서드를 호출하기 전에 엔터티 개체의 일부 멤버만 설정해야 합니다. 설정해야 하는 엔터티 멤버는 다음과 같은 조건을 충족해야 합니다.

  • 엔터티 ID의 일부여야 합니다.

  • 수정될 멤버여야 합니다.

  • 타임스탬프이거나 UpdateCheck 특성이 Never 이외의 값으로 설정되어 있어야 합니다.

테이블에 낙관적 동시성 검사를 위한 타임스탬프 또는 버전 번호가 사용되는 경우 Attach를 호출하기 전에 이러한 멤버를 설정해야 합니다. 해당 Column 특성에 IsVersion 속성이 true로 설정된 멤버는 낙관적 동시성 검사에 사용됩니다. 데이터베이스에 있는 버전 번호 또는 타임스탬프 값이 동일해야 요청된 업데이트가 제출됩니다.

UpdateCheck가 Never로 설정되지 않은 멤버도 낙관적 동시성 검사에 사용됩니다. 다른 값이 지정되지 않은 경우 기본값은 Always입니다.

이러한 필수 멤버가 하나라도 없으면 SubmitChanges를 호출했을 때 ChangeConflictException("행이 없거나 변경되었습니다.")이 throw됩니다.

상태

엔터티 개체를 DataContext 인스턴스에 연결하면 개체가 PossiblyModified 상태가 됩니다. 다음과 같은 세 가지 방법을 사용하여 연결된 개체를 강제로 Modified 상태로 만들 수 있습니다.

  1. 개체를 수정되지 않은 상태로 연결한 다음 필드를 직접 수정합니다.

  2. 개체의 현재 인스턴스와 원래 인스턴스를 사용하는 Attach 오버로드와 연결합니다. 이렇게 하면 이전 값과 새 값이 변경 추적기에 제공되므로 변경된 필드를 자동으로 인식할 수 있습니다.

  3. true로 설정된 두 번째 부울 매개 변수를 사용하는 Attach 오버로드와 연결합니다. 이렇게 하면 원래 값을 제공하지 않고도 수정된 개체를 변경 추적기에서 인식할 수 있습니다. 이 방법을 사용하려면 개체에 버전/타임스탬프 필드가 있어야 합니다.

+ Recent posts