私は複数の非常に異なるシステム間でデータを同期させるシナリオを持っています。このデータの同期は、各システムのオブジェクトハッシュとアイテムキーやその他の関連情報を格納するデータベーステーブルを持っています。いずれかのシステムからのオブジェクトのハッシュが変わると、私はもう一方を更新します。
私のデータベーステーブルは次のようになります。
CREATE TABLE [dbo].[SyncHashes](
[SyncHashId] [int] IDENTITY(1,1) NOT NULL,
[ObjectName] [nvarchar](50) NULL,
[MappingTypeValue] [nvarchar](25) NULL,
[MappingDirectionValue] [nvarchar](25) NULL,
[SourceSystem] [nvarchar](50) NULL,
[SourceKey] [nvarchar](200) NULL,
[SourceHash] [nvarchar](50) NULL,
[TargetSystem] [nvarchar](50) NULL,
[TargetKey] [nvarchar](200) NULL,
[TargetHash] [nvarchar](50) NULL,
[UpdateNeededValue] [nvarchar](max) NULL,
[CreatedOn] [datetime] NULL,
[ModifiedOn] [datetime] NULL,
[Version] [timestamp] NOT NULL,
[IsActive] [bit] NOT NULL,
PRIMARY KEY CLUSTERED
(
[SyncHashId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ここまでは順調ですね。しかし...
オブジェクトの MD5ハッシュ(これは私が使用しているものです)などのハッシュを効果的に計算するには、それをバイト配列に変換できる必要があります。 em>。
そして...
オブジェクトをバイト配列に変換するには、直列化可能でなければならないようです。 (少なくとも、これは私が読んだものであり、.NETから得られるエラーはそれが真実であると思われるようです。)
いずれかのシステムでは、すべてのデータベースオブジェクトをシリアライズ可能にする機能があります。ハッシュが生成され、すべてが同期され、世界は美しいです!
別のシステムでは、あまり大きくないです。 エンティティフレームワーク4 (コードファースト)モデルからデータベースコンテキストを渡され、エンティティは直列化されていません。
私が次のようなものを使ってバイトとしてキャストしようとすると、.NETは文句を叫び、小さな悩みを吹き飛ばします。
foreach(var dataItem in context.TableName)
{
var byteArray = (byte[]) dataItem;
}
OK。問題ない。
私は自分自身に、トリックをするかもしれないと思っていたちょっとした拡張メソッドを持っています。
public static byte[] ObjectToByteArray(this T obj)
{
if (obj == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, obj);
return ms.ToArray();
}
しかし、ああ、いいえ!オブジェクト(Entity)がシリアライズ可能でない場合、このルーチンはもう少し良い(そして完全に予想される)例外を投げます。
だから...私はルーチンを修正し、where節をメソッド定義に追加します。
public static byte[] ObjectToByteArray(this T obj) where T : ISerializable
{
if (obj == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
bf.Serialize(ms, obj);
return ms.ToArray();
}
唯一の問題は、バイト配列を取得するために、すべてのオブジェクトを直列化可能にする必要がある正方形に戻っていることです。
うーん。良くない。
そこで私は、オブジェクトのすべてのプロパティを繰り返し処理し、バイト配列を構築できる文字列表現を生成するためのハックをまとめました。それは醜いと不合理でしたが、それはある種のトリックでした。
public static string ComputeMD5Hash(this T input)
{
StringBuilder sb = new StringBuilder();
Type t = input.GetType();
PropertyInfo[] properties = t.GetProperties();
foreach (var property in properties)
{
sb.Append(property.Name);
sb.Append("|");
object value = property.GetValue(input, null);
if (value != null)
{
sb.Append(value);
}
sb.Append("|");
}
return MD5HashGenerator.GenerateKey(sb.ToString());
}
しかし...
結局のところ、まだ本当にできたいと思っているのは、クラスが直列化可能とマークされていないオブジェクトからバイト配列を効率的かつ適切に作成するです。これを達成する最良の方法は何ですか?
前もって感謝します!