변경된 유형에 대한 오래된 데이터를 어떻게 사로화합니까?
-
12-09-2019 - |
문제
다음 클래스에 이진 직렬화를 사용하여 저장된 데이터가 있습니다.
[Serializable]
public abstract class BaseBusinessObject
{
private NameValueCollection _fieldErrors = new NameValueCollection();
protected virtual NameValueCollection FieldErrors
{
get { return _fieldErrors; }
set { _fieldErrors = value; }
}
...
}
어느 시점에서 수업은 다음으로 변경되었습니다.
[Serializable]
public abstract class BaseBusinessObject
{
private Dictionary<string, string> _fieldErrors = new Dictionary<string, string>();
protected virtual Dictionary<string, string> FieldErrors
{
get { return _fieldErrors; }
set { _fieldErrors = value; }
}
...
}
이로 인해 오래된 데이터를 필수화하는 문제가 발생합니다.
나의 첫 번째 생각은 구현하는 것이었다 ISerializable
, 그러나이 클래스에는 수많은 속성과 수백 개의 상속 클래스가 있습니다.
사막화 중 현재 구조와 일치하도록 이전 데이터를 변경하거나 이전 데이터를 업그레이드하는 깨끗한 방법을 갖고 싶습니다.
해결책
새로운 추가 _fieldErrors
다른 이름으로 말하십시오 _fieldErrors2
, 그리고 그것을 만들어 [Optional]
. 그런 다음 구현하십시오 [OnDeserialized]
데이터를 복사하는 메소드 _fieldErrors
에게 _fieldErrors2
(존재하는 경우), _fielderrors를 제거합니다.
다른 팁
데이터가 내부적으로 만 사용되는 경우, 나의 첫 번째 생각은 기존의 "namevaluecollection"을 사용하여 바이너리 데이터를 제거하기 위해 간단한 던지기 코드를 작성하는 것입니다. 모든 데이터를 처리하는 데 며칠이 걸리더라도 이전 데이터를 지원하기 위해 새 코드의 패치를 구현하는 것이 가치가없는 것 같습니다.
내부적으로 만 사용 되더라도 수입업자는 가장 간단한 방법처럼 보입니다.
Olivierd의 좋은 조언에 추가하면 두 클래스를 모두 정의하는 것이 좋습니다. 그러나 처음에는 현재 버전으로 사막화하려고합니다. 캐치 블록에서 레거시 버전으로 사로화 한 다음 현재 버전으로 업그레이드하여 다시 저장하십시오. 레거시 버전의 인스턴스가 없으면 코드를 제거 할 수 있습니다.
몇 가지 옵션을 조사한 후 다음과 같은 결론을 내 렸습니다.
이상적으로는 원본에서 값에 액세스 할 수 있습니다. NameValueCollection
수동으로 변환합니다 Dictionary<string, string>
. 이를 수행하는 유일한 방법은 구현하는 것입니다. ISerializable
, 그러나 이것은 두 가지 주요 문제를 제기했습니다. 레거시 데이터의 명명과 일치하는 모든 상속 클래스 (수백 개)에 대한 직렬화 로직 포함.
효과적으로, 이것은 나를 바인드로 만들었습니다. 다행 스럽게도이 필드는 실제로 양식 검증 오류 요약으로 만 사용되며 처음에는 직렬화되지 않아야한다고 판단 할 수 있었으므로 직렬화에서 제외했습니다.