2009-05-28 1 views
0

데이터베이스에 두 개의 관련 테이블 인 페이지 및 태그가 있습니다. 한 페이지는 많은 태그와 관련 될 수 있습니다.LINQ에서 클래스 계층 구조 업데이트 당 한 번 저장된 프로 시저를 실행하려면 어떻게해야합니까?

이 두 테이블 중 하나를 수정할 때마다 BeforePageHierarchyUpdate라는 저장 프로 시저를 실행해야합니다.이 경우이 저장 프로 시저는 페이지 계층 구조에서 일부 로깅 및 버전 관리를 수행합니다. 페이지 인스턴스 또는 태그 인스턴스 중 하나가 업데이트되면 SP가 실행해야합니다

  1. : 나에게 문제를주고 무엇

    이 두 가지 요구 사항입니다. 그러나 페이지와 관련 태그 중 하나가 업데이트되면 SP는 한 번만 호출해야합니다.

  2. 저장 프로 시저는 다른 LINQ 문과 동일한 트랜잭션 내에 포함되어야합니다. LINQ 문이 실패하면 저장 프로 시저를 롤백해야합니다. 저장 프로 시저가 실패하면 LINQ 문을 실행하면 안됩니다.

아무에게도 이런 식으로 구현하는 방법에 대한 아이디어가 있습니까?

답변

0

일부 코드를 통해 파고 후, 여기에 또 다른 대안입니다. 연결/트랜잭션 코드가 정확하다는 점이 완전히 마음에 들지 않습니다 (기본 SubmitChanges 구현에서 대부분 리버스 엔지니어링되었습니다).

public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode) { 
    if (System.Transactions.Transaction.Current == null && this.Transaction == null) { 
     bool connectionOpened = false; 
     DbTransaction transaction = null; 
     try { 
      if (this.Connection.State == ConnectionState.Closed) { 
       this.Connection.Open(); 
       connectionOpened = true; 
      } 
      transaction = this.Connection.BeginTransaction(IsolationLevel.ReadCommitted); 
      this.Transaction = transaction; 

      BeforeSubmitChanges(); 
      base.SubmitChanges(failureMode); 

      transaction.Commit(); 
     } 
     catch { 
      if (transaction != null) { 
       try { 
        transaction.Rollback(); 
       } 
       catch { 
       } 
       throw; 
      } 
     } 
     finally { 
      this.Transaction = null; 
      if (connectionOpened) { 
       this.Connection.Close(); 
      } 
     } 
    } 
    else { 
     BeforeSubmitChanges(); 
     base.SubmitChanges(failureMode); 
    } 
} 

private void BeforeSubmitChanges() { 
    ChangeSet changes = this.GetChangeSet(); 
    HashSet<int> modifiedPages = new HashSet<int>(); 

    foreach (Page page in changes.Updates.OfType<Page>()) { 
     modifiedPages.Add(page.PageId); 
    } 

    foreach(PageTag tag in changes.Updates.OfType<PageTag>()) { 
     modifiedPages.Add(tag.PageId); 
    } 

    foreach (PageTag tag in changes.Inserts.OfType<PageTag>()) { 
     //If the parent is being inserted, don't run the Update SP. 
     if (!changes.Inserts.Contains(tag.Page)) { 
      modifiedPages.Add(tag.PageId); 
     } 
    } 

    foreach (PageTag tag in changes.Deletes.OfType<PageTag>()) { 
     //If the parent is being deleted, don't run the Update SP. 
     if (!changes.Deletes.Contains(tag.Page)) { 
      modifiedPages.Add(tag.PageId); 
     } 
    } 

    foreach (int pageId in modifiedPages) { 
     this.BeforePageHierarchyUpdate(pageId); 
    } 
} 
+0

더 좋든 나 싫든이 것은 현재 제가 사용하고있는 구현물입니다. 마음이 바뀌면이 질문을 업데이트하는 것을 잊지 않도록 노력할 것입니다. – AaronSieb

0

에만 다음 절차를 사용하여이 테이블을 갱신 :

create procedure UpdatePageAndOrTag 
(
    @mode    char(1) --"P"=page only, "T"=tag only, "B"=both 
    ,@pageParam1 ... 
    ,@pageParam2 .... 
    .... 
    ,@TagParam1..... 
    ,@TagParam2.... 
    .... 
) 

as 

EXEC BeforePageHierarchyUpdate 

if @Mode="B" or @Mode="P" 
Begin 
    update Page.... 
END 

IF @Mode="B" or @Mode="T" 
Begin 
    update tag... 
END 

return 0 
go 
+0

하나의 페이지와 연결된 여러 태그를 업데이트해야하는 경우 어떻게해야합니까? – AaronSieb

+0

"배열"(쉼표로 구분 된 목록) 문자열을 전달하고 저장 프로 시저에서 분할 : http://www.sommarskog.se/arrays-in-sql.html, 나는이 방법을 좋아한다 : http : // www.sommarskog.se/arrays-in-sql-2005.html#tblnum, INSERT의 SELECT FROM에있는 여러 매개 변수를 임시 테이블로 분할 한 다음 거기에서 집합으로 작업 할 수 있습니다. 쉼표로 구분 된 여러 개의 목록 매개 변수를 사용하여 작업하는 것에 대한 다른 질문을하고 그에 대한 많은 정보를 얻을 수 있습니다. –

+0

LINQ의 변경 내용 추적을 사용하면 어떻게 구현 될까요? 아니면 명시 적으로 호출해야합니까? – AaronSieb

0

세 번째 잠재적 인 솔루션은 저장소 클래스 (또는 다른 랩핑 구현)에 넣는 것입니다. 이렇게하면 트랜잭션 코드가 상당히 단순 해지지 만 기능이 DataContext 레이어에서보다 적절하다고 느껴집니다.

public class PageRepository : IPageRepository { 
    public void Save() { 
     using(TransactionScope trans = new TransactionScope()) { 
      BeforeSubmitChanges(); 
      mDataContext.SubmitChanges(); 
      trans.Complete(); 
     } 
    } 

    private void BeforeSubmitChanges() { 
     ChangeSet changes = this.GetChangeSet(); 
     HashSet<int> modifiedPages = new HashSet<int>(); 

     foreach (Page page in changes.Updates.OfType<Page>()) { 
      modifiedPages.Add(page.PageId); 
     } 

     foreach(PageTag tag in changes.Updates.OfType<PageTag>()) { 
      modifiedPages.Add(tag.PageId); 
     } 

     foreach (PageTag tag in changes.Inserts.OfType<PageTag>()) { 
      //If the parent is being inserted, don't run the Update SP. 
      if (!changes.Inserts.Contains(tag.Page)) { 
       modifiedPages.Add(tag.PageId); 
      } 
     } 

     foreach (PageTag tag in changes.Deletes.OfType<PageTag>()) { 
      //If the parent is being deleted, don't run the Update SP. 
      if (!changes.Deletes.Contains(tag.Page)) { 
       modifiedPages.Add(tag.PageId); 
      } 
     } 

     foreach (int pageId in modifiedPages) { 
      this.BeforePageHierarchyUpdate(pageId); 
     } 
    } 
} 
관련 문제