2016-09-15 13 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にそのプロパティをどのように格納して取得するべきかを伝える必要があります。

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

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

しかし、この解決策は、エラーを起こしやすい、とそのプロパティを持つ特殊なワークフローが続いている必要があります。私は、エンティティに1つのより多くのプロパティを格納することができ

を試してみましたが、何

P.S.実際には、この質問は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

_ハッシュがエンティティフレームワーク – Monah

+0

@ hadi yeaで動作するかどうか、私はそれを試して、varbinary(max)に保存しました - これは生成され、バックアップされました - 問題ありません。 – Jim

+0

@ジム、これはより洗練されたソリューションです。 – stukselbax

関連する問題