2009-04-30 8 views
3

は、私は、このようなクラスがあるとしましょう:NHibernateを使用してオブジェクトをxmlシリアル化された形式で格納できますか?

public class MyClass 
{ 
    public int Id { get; set; } 

    public DateTime Date { get; set; } 
    public string String1 { get; set; } 
    public string String2 { get; set; } 
    public string String3 { get; set; } 
    public string String4 { get; set; } 
} 

それはNHibernateのは、次のスキーマでそれを保存するために取得することはできますか?

CREATE TABLE [dbo].[MyClass](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [Xml] [varchar](max) NOT NULL, 
) 

IdはIdにマップされますが、他のフィールドはすべてXMLにシリアル化されますか?

public class MyClass 
{ 
    public int Id { get; set; } 

    public AllOtherOptions Options { get; set; } 
} 

public class AllOtherOptions 
{ 
    public DateTime Date { get; set; } 
    public string String1 { get; set; } 
    public string String2 { get; set; } 
    public string String3 { get; set; } 
    public string String4 { get; set; } 
} 

答えて

4

私は今後のプロジェクトのために似た何かを考えています。これらの他のフィールドは、それが助け場合は、以下のような子オブジェクトに行かなければならない場合、私は気にしません。プロジェクトでは多くのデータを収集する必要がありますが、リレーショナルデータベースに保存する必要がある要素はわずかです。私は実験を始めませんでしたが、これはこれまでの私の考えです。

IUserTypeを実装する型を作成することにより、XMLデータ型をマップできます。子クラス(AllOtherOptions)がシリアライズ可能な場合は、XMLフィールドをMyClassのプライベートメンバーとしてマップし、必要に応じてAllOtherOptionsをシリアル化/逆シリアル化できます。あなたは、XMLフィールドを動的に維持するか(多くの作業のように聞こえる)、またはインターセプタを作成してそれを行うことができます。私の考えは、MyClassは、

public interface IXmlObjectContainer 
{ 
    void SerializeChildObjects(); 
    void DeSerializeChildObjects(); 
} 

などのインターフェイスを実装し、インターセプタはこれらのメソッドを必要に応じて呼び出すということです。それはコンセプトのアイデアです。おそらく、xmlフィールドと直列化可能オブジェクトのペアを公開して、IXmlObjectContainer実装者からシリアライズする作業を取り除くことで、これを改良するでしょう。または、XMLフィールドのget/setアクセサを使用してシリアル化を処理することもできます。

さらに詳しい情報:

  1. Working with XML Fields in NHibernate
  2. Another XML implementation of IUserType
+0

かなりエレガントなソリューションのようです。私はそれが好きです。 –

+2

あなたの型が[Serializable]とマークされている場合、マッピングに "type =" serializable ""を追加すると、自動的にバイナリ(de)がリンクされてくれたtho +1 –

+0

興味深い。私は、これはBLOBデータ(http://msdn.microsoft.com/en-us/library/ms345117.aspx)とDbType.Binary(http:// nhforge)へのシリアライズ可能なマップとしてXMLを格納するため、SQL Server上でのみ動作すると思います。 org/doc/nh/en/index.html#mapping-types)。 –

2

私は、XML列にオブジェクトを保存するために、同じ考えを持っていました。私の考えは他だった。私はリンクからコードを取り出し、一般的なIUserTypeの実装に変更しました。したがって、[Serializable]であるフィールド/プロップはXML列に保存できます。 FluentNHibernateと

public class XmlUserType<T> : IUserType where T : class 
{ 
    public new bool Equals(object x, object y) 
    { 
    return x == y; 
    } 

    public int GetHashCode(object x) 
    { 
    return x.GetHashCode(); 
    } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
    if (names.Length != 1) 
     throw new InvalidOperationException("names array has more than one element. can't handle this!"); 

    var val = rs[names[0]] as string; 

    if (string.IsNullOrWhiteSpace(val) == false) 
    { 
     return KRD.Common.GenericXmlSerialization.Deserialize<T>(val); 
    } 

    return null; 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
    var parameter = (DbParameter)cmd.Parameters[index]; 
    T toSave = value as T; 

    if (toSave != null) 
    { 
     parameter.Value = KRD.Common.GenericXmlSerialization.Serialize(toSave); 
    } 
    else 
    { 
     parameter.Value = DBNull.Value; 
    } 
    } 

    public object DeepCopy(object value) 
    { 
    T toCopy = value as T; 

    if (toCopy == null) 
     return null; 

    string serialized = KRD.Common.GenericXmlSerialization.Serialize(toCopy); 

    return KRD.Common.GenericXmlSerialization.Deserialize<T>(serialized); 
    } 

    public object Replace(object original, object target, object owner) 
    { 
    throw new NotImplementedException(); 
    } 

    public object Assemble(object cached, object owner) 
    { 
    var str = cached as string; 
    if (string.IsNullOrWhiteSpace(str) == false) 
    { 
     return null; 
    } 

    return KRD.Common.GenericXmlSerialization.Deserialize<T>(str); 
    } 

    public object Disassemble(object value) 
    { 
    var toCache = value as T; 

    if (toCache != null) 
    { 
     return KRD.Common.GenericXmlSerialization.Serialize(toCache); 
    } 

    return null; 
    } 

    public SqlType[] SqlTypes 
    { 
    get 
    { 
     return new SqlType[] { new SqlXmlType() }; 
    } 
    } 

    public Type ReturnedType 
    { 
    get { return typeof(XmlDocument); } 
    } 

    public bool IsMutable 
    { 
    get { return true; } 
    } 
} 

public class SqlXmlType : SqlType 
{ 
    public SqlXmlType() 
    : base(DbType.Xml) 
    { 
    } 
} 

使用法:

public class MainObject 
    { 
    public int Id { get; set; } 

    public ObjectAsXml Data { get; set; } 
    } 

    public class ObjectAsXml 
    { 
    public string Name { get; set; } 

    public int Date { get; set; } 

    public ObjectAsXml OtherObject { get; set; } 
    } 

    private class MainObjectMap : ClassMap<MainObject> 
    { 
    public MainObjectMap() 
    { 
     Id(id => id.Id); 
     Map(m => m.Data).CustomType<XmlUserType<ObjectAsXml>>().Nullable(); 
    } 
    } 

多分それが誰かを助けます。

+0

共有してくれてありがとう、1つの質問私は 'KRD.Common.GenericXmlSerialization'はカスタムxmlシリアライザだと仮定しますか? –

+1

はい、内部は標準の.netシリアライザです。これはヘルパークラスのみです – szkra

関連する問題