2016-09-15 10 views
6

ADO.NET을 사용하여 영구 저장소에 액세스하는 이전 프로젝트가 있습니다. 현재 최소한의 코드 중복으로 여러 DB 공급자를 지원하기 위해 EF (6.1.3, 중요하다면)로 마이그레이션하려고합니다.EntityFramework를 사용하여 데이터베이스에서 엔터티의 Hashtable 속성을 처리하는 방법

Hashtable 특성이 포함 된 엔티티가 : ADO.NET으로

public class Record 
{ 
    ... 
    public Hashtable data { get; set; } 
} 

BinaryFormatter은 BLOB이 data 속성을 변환하는 데 사용되었으며, 그 반대의 경우도 마찬가지 :

using (MemoryStream stream = new MemoryStream()) 
{ 
    BinaryFormatter formatter = new BinaryFormatter(); 
    formatter.Serialize(stream, data); 
    result = stream.GetBuffer(); 
} 

//---------- 

using (MemoryStream serializationStream = new MemoryStream((byte[])value)) 
{ 
    BinaryFormatter formatter = new BinaryFormatter(); 
    result = (Hashtable)formatter.Deserialize(serializationStream); 
} 

이제는 EF에 그 속성을 저장하고 가져 오는 방법을 EF에 알려야합니다.

public class Record 
{ 
    public byte[] dataRaw { get; set; } 

    [NotMapped] 
    public Hashtable data { 
     get {/*deserialize dataRaw */ } 
     set { /*Serialize to dataRaw*/} 
    } 
} 

그러나이 솔루션은 오류를하는 경향이, 그 속성을 특정 워크 플로가 따라야합니다 : 내가 엔티티에 또 하나 개의 속성을 저장할 수

노력이 무엇

.

P. 사실이 질문은 Hashtable에 관한 것이 아니라 특별한 방식으로 저장 및 검색해야하는 모든 사용자 정의 클래스에 관한 것입니다.

+0

솔직히이 가능하다고 생각하지 않습니다. 나는 값이 SQL 프리미티브의 안팎으로 강제로 허용되는 훅이 있다고 생각하지 않는다. 나는이 질문을 간절히 바라보고 있으면 어떤 대답이 있는지보기 위해 열심히 노력하고 있습니다. – Jim

+0

비슷한 질문이 있습니다. http://stackoverflow.com/questions/16135642/in-entity-framework-is-there-a-cleaner-way-of-converting-an-object-type-to-a-str, 그것은 당신과 같은 뒷받침 필드를 사용합니다. 나는 다른 방법이 있다고 생각하지 않는다. – Jim

답변

5

여기 위에서 언급 한 answer을 기반으로하는 완벽한 솔루션입니다.
linqpad에서 테스트 해 보았지만 제대로 작동합니다.

속성 접근자가 필요한 경우 해시 테이블을 저장하고로드하므로 특별한 워크 플로가 필요하지 않습니다. [값을 변환 할 수

홈페이지 방법

void Main() 
{ 
    using (var ctx = new TestContext()) 
    { 
     var hash = new Hashtable(); 
     hash.Add("A", "A"); 
     ctx.Settings.Add(new Settings { Hash = hash }); 
     ctx.SaveChanges(); 

     // load them up... 
     ctx.Settings.ToArray().Select(_ => _.Hash).Dump(); 
    } 
} 

설정 클래스

public class Settings 
{ 
    // a primary key is necessary. 
    public int Id { get; set; } 

    [NotMapped] 
    public Hashtable Hash 
    { 
     get; 
     set; 
    } 

    // the backing field can be protected, this helps 'hide' it. 
    protected virtual byte[] _Hash 
    { 
     get 
     { 
      return Hash.ToBinary(); 
     } 
     set  
     { 
      Hash = value.FromBinary<Hashtable>(); 
     } 
    } 
} 

확장

public static class Extensions 
{ 

    public static BinaryPropertyConfiguration BinaryProperty<T>(
     this EntityTypeConfiguration<T> mapper, 
     String propertyName) where T : class 
    { 
     Type type = typeof(T); 
     ParameterExpression arg = Expression.Parameter(type, "x"); 
     Expression expr = arg; 

     PropertyInfo pi = type.GetProperty(propertyName, 
      BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); 
     expr = Expression.Property(expr, pi); 

     LambdaExpression lambda = Expression.Lambda(expr, arg); 

     Expression<Func<T, byte[]>> expression = (Expression<Func<T, byte[]>>)lambda; 
     return mapper.Property(expression); 
    } 

    public static byte[] ToBinary<T>(this T instance) 
    { 
     if (instance == null) 
      return null; 

     using (var stream = new MemoryStream()) 
     { 
      var formatter = new BinaryFormatter(); 
      formatter.Serialize(stream, instance); 
      return stream.ToArray(); 
     } 
    } 

    public static T FromBinary<T>(this byte[] buffer) 
    { 
     if (buffer == null) 
      return default(T); 

     using (var stream = new MemoryStream(buffer, false)) 
     { 
      var formatter = new BinaryFormatter(); 
      var instance = formatter.Deserialize(stream); 
      return (T)instance; 
     } 
    } 
} 

데이터 컨텍스트

public class TestContext : DbContext 
{ 
    public DbSet<Settings> Settings { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 
     modelBuilder 
      .Entity<Settings>() 
      .BinaryProperty("_Hash") 
      .HasColumnName("Hashtable"); 
    }  
} 
+0

_Hash가 엔티티 프레임 워크 – Monah

+0

@ hadi yea와 함께 작동하는지 궁금합니다. 작동합니다. varbinary (최대)에 저장했습니다. 생성 된 것이고 다시로드되었습니다. 문제 없습니다. – Jim

+0

@ 짐,이게 더 우아한 해결책입니다. – stukselbax