2009-09-21 3 views
15

저는 Entity Framework의 일부 감사 훅을 조사했습니다. 그들 중 많은 수가 이전/새로운 가치 비교를 보여줍니다. 이것은 감사 추적에 유용하지만 스냅 샷 객체를 찾고 있습니다.Entity Framework를 사용한 스냅 숏 기록

예를 들면 ... 제품을 관리하는 응용 프로그램이 있다고 가정 해 봅니다. 제품에는 여러 속성과 연관된 다른 객체가 있습니다. 객체를 10 번 변경한다고 가정 해 보겠습니다. 이러한 변경 사항의 화면 (감사 내역이 아니라 화면이 실제로 읽기 전용 형식으로 표시되는 화면)을 볼 수 있어야한다는 점도 중요합니다. 내가 관심있는 부분은 10 개의 모든 변경 사항 (관련 정보가있는 모든 원본 데이터)을 원래 EF 제품 개체에서 가져 와서 내 화면에 바인딩하는 데 사용할 수 있다는 것입니다.

SQL Server를 사용하는 경우 요즘 (XML, blob 등) 직렬화 된 개체에 어떤 형식을 사용해야합니까? 이것을하는 것이 합리적입니까?

+0

나는 더 상세한 대답을 얻기 위해 현상금을 추가 할 것이다 :) –

+1

@AnynameDonotcare는 히스토리를 저장할 각 테이블에 대해 다음을 수행한다. 1) 버전 열을 추가한다 (카운터가 증가 할 수있다). 2) 기본 테이블과 동일한 모든 등록 정보를 가진 다른 테이블을 추가하십시오 (그러나 외래 키를 더 잘 확장하십시오). 3) 업데이트 전 트리거에서 버전 열이 변경된 경우 - 이전 버전 값을이 버전 테이블에 복사합니다. 4) 이익. – Evk

+0

@Evk : 간단한 예제 ('EF'사용)로 상세한 답변을 추가 할 수 있다면 매우 기쁠 것입니다. (삭제 작업 및 mm 관계와 관련하여) 기업용 애플리케이션의 기반으로 사용될 수 있습니다. –

답변

11

보겠습니다. 객체 그래프를 가져 와서 나중에 구체화 할 수있는 형식으로 데이터베이스에 직렬화해야한다는 요구 사항이 있습니다. 나는 정확하게 이것을하는 도구가 있다고 생각한다. 그 중 하나가 Entity Framework입니다.

당신이하고 싶은 일은 매우 일반적입니다. 위키 엔진을 고려하십시오. 위키에는 모든 사람이 볼 수있는 팁 수정본과 모든 문서의 수정본이 있어야합니다. 또한 위키는 팁 수정본이 표시되는 것과 같은 방식으로 뒷 버전을 표시 할 수 있어야합니다. 따라서 두 가지 모두 동일한 저장 형식을 사용해야합니다.

모든 엔티티 유형의 버전을 허용 할 것을 제안합니다. 엔티티 유형을 편집 할 때 팁 리비전을 편집하고 이전 값을 포함하는 이전 리비전을 저장합니다. (새 팁을 삽입하는 대신 팁 개정을 편집하는 이유는 현재 ObjectContext에 구체화되지 않은 다른 객체에 링크가 아닌 팁에 대한 링크로 유지하려는 팁에 대한 링크를 포함 할 수 있기 때문입니다

필요한 경우 SQL Server 테이블을 분할하여 이전 버전이 다른 파일 그룹에 저장되도록 할 수 있습니다. 이렇게하면 팁 수정본과 수정본을 따로 백업 할 수 있습니다.

+0

아주 좋은 아이디어 ... – RailRhoad

+0

'나는 당신이 당신의 모든 엔티티 타입이 버전 화되도록 허락 할 것을 제안 할 것입니다 .' 당신이 의미하는 바를 좀 더 명확히 해줄 수 있습니까? –

3

내가 최근에 만든 프로젝트에서는 DbContext 클래스의 SaveChanges 메서드를 사용했습니다. 이로써 ChangeTracker 클래스의 인스턴스에 액세스 할 수있었습니다. ChangeTracker.Entries()을 호출하면 DbEntityEntry의 목록에 액세스 할 수 있습니다.

  • State 객체의 복사본이
  • CurrentValues의 약자로 - - - 새로 생성, 수정 또는
  • Entity
  • 를 삭제되는 개체는 편집의 열거 : DbEntityEntry는 다음과 같은 흥미로운 속성과 메소드를 가지고
  • OriginalValues
  • 평가 - 원래 값

의 열거 우리는 세트를 생성 EF를 통해 액세스 할 수있는 변경 세트 및 변경 사항에 대한 POCO. 이를 통해 사용자는 날짜와 책임있는 사용자와 함께 필드 레벨 변경 사항을 볼 수있었습니다.

3

먼저 당신은 당신의 테이블에 속성 세트를 추가해야합니다

  • 버전 - 마지막 수정 시간을 (대신 시간 카운터를 autoincrementing 될 수 있습니다).
  • LastModifiedBy - 마지막 수정을 한 사용자에 대한 참조 (저장 한 경우).

그런 다음 버전 기록을 저장하는 방법에 대한 몇 가지 옵션이 있습니다. 당신은 할 수있다

  1. 히스토리를 저장할 각각의 메인 테이블에 대해 새로운 테이블을 만든다. 히스토리 테이블은 주 테이블과 동일한 필드를 갖지만 기본 키와 외래 키는 시행되지 않습니다. 각 외래 키에 대해서도 버전을 만들 때 참조 된 항목의 버전을 저장하십시오.

  2. 또는 엔티티에 관한 모든 흥미로운 내용을 직렬화하고 버전을 지정하려는 모든 엔티티에 대한 모든 직렬화 된 모양을 하나의 전역 기록 테이블에 저장할 수 있습니다 (개인적으로는 첫 번째 방법을 선호합니다).

히스토리 테이블을 어떻게 채우십니까? 업데이트 및 삭제 트리거를 통해.

  • 엔티티의 업데이트 트리거에서 - 모든 이전 값을 기록 테이블에 복사하십시오. 각 외래 키에 대해서도 참조 된 엔터티의 현재 버전을 복사하십시오.
  • 삭제 트리거에서 - 기본적으로 동일하게 수행합니다.

점점 더 많은 현대 시스템이 실제로 아무것도 삭제하지 않는다는 것에 유의하십시오. 그들은 단지 표시 삭제 된 것과 같습니다. 이 패턴을 따르고 싶다면 엔티티에 IsDeleted 플래그를 추가하는 대신 여러 가지 이점이 있습니다. 물론 삭제 된 엔티티를 모든 곳에서 필터링해야합니다.

기록을 어떻게 봅니까? 메인 테이블과 동일한 속성을 가지고 있기 때문에 히스토리 테이블 만 사용하면된다. 하지만 - 외래 키를 확장 할 때 - 참조 된 엔터티 버전이 내역 테이블에 저장하는 것과 동일한 지 확인하십시오. 그렇지 않은 경우 - 해당 참조 된 엔터티의 기록 테이블로 이동하여 값을 가져와야합니다. 이 방법을 사용하면 모든 참조를 포함하여 엔티티가 그 순간에 어떻게 보였는지 항상 파악할 수 있습니다.

위의 모든 것 외에도 이전 버전으로 엔티티의 상태를 복원 할 수도 있습니다.

스냅을 저장하기 때문에이 구현은 쉽지만 약간의 공간을 소비 할 수 있습니다. 변경 사항을 저장하려는 경우 - 업데이트 트리거에서 어떤 필드가 변경되었는지 감지하고 일련 화 한 후 글로벌 기록 테이블에 저장할 수 있습니다. 그렇게하면 사용자 인터페이스에서 변경된 내용과 누구에게 표시 할 수 있습니다 (이전 버전으로 되 돌리는 데 문제가있을 수 있음).

+0

더 많은 중복 데이터가 포함되어 있고 더 많은 db 스토리지가 필요하지만 두 번째 방법보다 첫 번째 방법을 선호하는 이유는 무엇입니까? 트리거는 'EF'를 통해 이러한 모든 작업을 처리하려는 것 외에도 성능 문제를 일으 킵니다. 간단한 예제 (두 개의 테이블)를 제공 할 수 있습니까 –

+0

처음으로 "트리거로 성능 문제가 발생합니다"라는 말을 들었습니다. 내부의 무거운 논리를 수행하는 경우에만 트리거가 자체 트리거를 일으킬 수 없습니다. 모두 당신은 완전히 동일한 방식으로 EF에서 그렇게 할 수 있습니다. 단지 업데이트 핸들러에서 모든 현재 값을 히스토리 테이블에 먼저 복사합니다 (여기서 제공 할 수있는 예제는 확실하지 않습니다. 하나의 엔티티에서 값을 복사하는 방법을 알고 있다고 생각합니다). 다른). 나는 더 간단하고 명확하기 때문에 첫 번째 접근법을 선호합니다. 게다가 이전 버전으로 쉽게 복원 할 수 있습니다. 이 외에도 - history에서 _search_를 사용할 수 있습니다 (직렬화하면 수행하기가 더 어려울 수 있음). – Evk

+0

내가 'EF'를 통해 트리거 논리를 처리하려면 트랜잭션에 있어야합니까? –

관련 문제