2010-03-19 2 views
1

실제로 프런트 엔드 UI를 통해 편집 할 수있는 XML 문서가 있습니다. 나는이 접근 방식에 문제가 있음을 발견했다. (데이터베이스 대신 xml 파일을 사용하고 있다는 사실 외에도 ... 지금은 변경할 수 없다.)부분적으로 XML 직렬화 된 문서 수정

다른 사용자가 변경 작업을 수행하는 동안 한 사용자가 변경 한 경우 두 번째 사용자가 변경하면 첫 번째 사용자가 변경 사항을 덮어 씁니다.

XML 파일에서 개체를 요청하고 변경 한 다음 전체 파일을 다시 쓰지 않고 XML 파일로 변경 사항을 다시 제출할 수 있어야합니다. 내 전체 XML 액세스 클래스 (유래에서 멋진 도움에 감사를 형성 한!)

using System; 
using System.Linq; 

using System.Collections; 
using System.Collections.Generic; 

namespace Repositories 
{ 
    /// <summary> 
    /// A file base repository represents a data backing that is stored in an .xml file. 
    /// </summary> 
    public partial class Repository<T> : IRepository 
    { 
     /// <summary> 
     /// Default constructor for a file repository 
     /// </summary> 
     public Repository() { } 

     /// <summary> 
     /// Initialize a basic repository with a filename. This will have to be passed from a context to be mapped. 
     /// </summary> 
     /// <param name="filename"></param> 
     public Repository(string filename) 
     { 
      FileName = filename; 
     } 

     /// <summary> 
     /// Discovers a single item from this repository. 
     /// </summary> 
     /// <typeparam name="TItem">The type of item to recover.</typeparam> 
     /// <typeparam name="TCollection">The collection the item belongs to.</typeparam> 
     /// <param name="expression"></param> 
     /// <returns></returns> 
     public TItem Single<TItem, TCollection>(Predicate<TItem> expression) 
      where TCollection : IDisposable, IEnumerable<TItem> 
     { 
      using (var list = List<TCollection>()) 
      { 
       return list.Single(i => expression(i)); 
      } 
     } 

     /// <summary> 
     /// Discovers a collection from the repository, 
     /// </summary> 
     /// <typeparam name="TCollection"></typeparam> 
     /// <returns></returns> 
     public TCollection List<TCollection>() 
      where TCollection : IDisposable 
     { 
      using (var list = System.Xml.Serializer.Deserialize<TCollection>(FileName)) 
      { 
       return (TCollection)list; 
      } 
     } 

     /// <summary> 
     /// Discovers a single item from this repository. 
     /// </summary> 
     /// <typeparam name="TItem">The type of item to recover.</typeparam> 
     /// <typeparam name="TCollection">The collection the item belongs to.</typeparam> 
     /// <param name="expression"></param> 
     /// <returns></returns> 
     public List<TItem> Select<TItem, TCollection>(Predicate<TItem> expression) 
      where TCollection : IDisposable, IEnumerable<TItem> 
     { 
      using (var list = List<TCollection>()) 
      { 
       return list.Where(i => expression(i)).ToList<TItem>(); 
      } 
     } 

     /// <summary> 
     /// Attempts to save an entire collection. 
     /// </summary> 
     /// <typeparam name="TCollection"></typeparam> 
     /// <param name="collection"></param> 
     /// <returns></returns> 
     public Boolean Save<TCollection>(TCollection collection) 
     { 
      try 
      { 
       // load the collection into an xml reader and try to serialize it. 
       System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument(); 
       xDoc.LoadXml(System.Xml.Serializer.Serialize<TCollection>(collection)); 

       // attempt to flush the file 
       xDoc.Save(FileName); 

       // assume success 
       return true; 
      } 
      catch 
      { 
       return false; 
      } 
     } 


     internal string FileName { get; private set; } 
    } 

    public interface IRepository 
    { 
     TItem Single<TItem, TCollection>(Predicate<TItem> expression) where TCollection : IDisposable, IEnumerable<TItem>; 
     TCollection List<TCollection>() where TCollection : IDisposable; 
     List<TItem> Select<TItem, TCollection>(Predicate<TItem> expression) where TCollection : IDisposable, IEnumerable<TItem>; 

     Boolean Save<TCollection>(TCollection collection); 
    } 
} 
+0

안녕하세요! 개정 관리 시스템을 구현하는 것 같습니다. 다음과 같이 하시겠습니까? - 잠금 장치를 구현하십시오. - XML을 인식하는 3 가지 방식의 병합. - 다른 것을 시도해보십시오. – dtb

+0

한숨. 나는 정말로 모른다. 이 전체 프로젝트는 어리 석다 - 그것은 모든 데이터베이스에 의해 더 나은 서비스를 제공 할 것이지만 나는 그것을 위해 하나를 설정하고 데이터를 전송할 시간이 없다. – Ciel

답변

1

를 사용하면 XML 문서 형식의 유연성이있는 경우, 다음 몇 가지 경우가 있습니다 할수있다.

하나의 가능성 :

  • 파일을 열 때, 하나의 메모리로, 전체 사본을로드, 또는 임시 파일로.
  • 편집하는 동안 변경 사항을 기록하고 파일을 수정하지 마십시오.
  • 자주 (1 분마다) 외부 파일의 변경 내용이로드됩니다. 파일 시스템이 파일 시스템을 지원하면 변경 사항을 모니터링하고 파일이 기록 될 때 즉시 새로 고칩니다.
  • 저장시 파일을 쓰기 위해 잠그고 로컬로 수정 된 섹션에 대한 충돌하는 외부 변경 사항이 없는지 확인하십시오.
  • 선택을 취소했다면 변경하고 파일을 놓습니다.
  • 충돌이있는 경우 어쨌든 어떻게 든 처리해야합니다.

앱을 사용하면 자동으로 로컬 사본을 자동 저장하고 새로 고침하여 충돌을 줄일 수 있습니다. 사용자 개입없이 자동 저장을 수행하는 경우 뛰어난 실행 취소 기능이 있는지 확인하십시오.

+0

나는 당분간 이것이 내가해야 할 일이라고 생각한다. 내가 문제가되는 것은 웹 애플리케이션에 있기 때문에 모든 사람이 액세스 할 수있는 메모리를 선언하는 방법을 알아내는 것입니다. – Ciel

+0

나는 각 클라이언트가 자신의 in-memory 또는 temp 파일 복사본을 가지고있는 데스크탑 애플 리케이션 관점에서 이것을 생각하고있었습니다. 이것을 각 세션이 자신의 사본으로 작동하도록 세션까지 확장 할 수 있습니다. – Eclipse

1

나는 데이터베이스를 사용하는 이유를 배우는 것 같아 여기에 게시있어.

여러 스레드가 동일한 XML 문서를 디스크에 쓰는 것은 불가능합니다. 디스크 문서의 메모리 내 사본을 유지 관리하는 일부 중앙 서비스에 변경 사항을 제출하는 설정이 필요합니다. 각 변경 사항을 메모리로 업데이트 한 다음 디스크로 플러시합니다. 이를위한 중앙 서비스이므로 업데이트 요청을 직렬화하여 일관성있는 문서를 보장 할 수 있습니다.

결과 문서를 클라이언트에 제공해야한다고 가정합니다.

+0

나는 이것을 끝내기 위해 19 시간이 넘었고 나는 데이터베이스로 그것을하는 방법을 모른다. 그것은 이유를 알지 못하는 문제가 아니며 절대적인 물리적 불가능 성의 문제입니다. – Ciel

+0

나는 그 시간에 할 수 없다고 말했지만, 관리자는 이성을 거의 듣지 않습니다. – Ciel

+0

모든 제안을 주셔서 다시 한 번 감사드립니다. 실제 전문가의 의견을 수렴하면 내 관리자가 프로젝트의이 부분에서 타임 라인을 연장하도록 설득하게됩니다. – Ciel

1

많은 문제가 있기 때문에 문제에 대한 간단한 해결책이 없다고 생각합니다. 전체 파일을 다시 작성하지 않고 XML 파일을 업데이트 할 수는 없지만 여러 개가있는 경우 자원 잠금에 관심을 가져야한다는 점 사용자는 동시에 데이터에 액세스합니다. 그 문제에 대한 쉬운 해결책은 없습니다!

게시 한 클래스가 나에게도 이상하게 보입니다. 왜 나중에 XmlDocument로 직렬화하여 디스크에 기록합니까? 디스크에 즉시 직렬화하지 않는 이유는 무엇입니까? 예외를 잡아 내고 무시하는 것은 매우 나쁜 스타일입니다!

+0

그래, 알아. 왜 내가 먼저 문서에 파이프를 연결하는지에 관해서는, 그것은 이전 시리얼 라이저에서 가지고있는 코드 일뿐입니다.이를 수정해야합니다. – Ciel

2

Xml은 고정 폭 레코드 형식이 아닙니다. 내부 쓰기를 다시 작성하지 않고 편집하는 것은 매우 어렵습니다 (읽으십시오 : 귀찮게하지 마십시오). xml의 ​​가장 합리적인 사용 사례에서 이것은 훌륭하고 예상됩니다. 이것이 문제라면, 대체 저장 메커니즘 (데이터베이스가 떠오른다)을 고려하고 필요할 때 xml을 간단히 가져 오거나 내보낼 수 있습니다.

1

내가 볼 수있는 한 멀리 갈 수있는 2 가지 방법이 있습니다. 하나 이상의 사람이 한 번에 주어진 파일을 수정하지 못하게하는 잠금 메커니즘을 구현합니다. 두 사람이 동시에 변경을 할 수있게하는 방법을 묻는다면, 나는 이것을 할 수 없다고 생각할 것입니다.

다른 방법은 추악하고 실제 못합니다. 그러나 그것은 효과가있다. 기본적으로 저장소를 싱글 톤 (모든 사용자 요청에 대해 단 하나의 정적 참조)으로 바꾸고 메모리에서 파일을 "편집"하십시오. 모든 변경 설정 후에 변경 사항을 디스크에 저장하십시오. 메모리에있는 정보의 사본 하나에 대한 작업을하기 때문에 한 사용자는 다른 사람의 정보를 덮어 쓰지 않습니다. (둘 다 구성 요소를 변경하지 않는 한)

이 기능을 사용하려면 잠금을 구현해야합니다. (당신은 기본적으로 멀티 스레드 환경에서 각 스레드로 요청하고, 프로그램을 치료하는 것입니다.

행운을 빌어 요 ...