2009-04-30 124 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

聽起來像一個相當優雅的解決方案;我喜歡。 – 2009-05-01 14:42:01

+2

我發現如果你的類型是用[Serializable]標記的,如果你添加了「type =」serializable「」到你的映射,NH會自動爲你進行二進制(de)序列化,這對我來說是工作的,謝謝你的鏈接tho +1 – 2009-05-01 17:25:36

2

我有同樣的想法,以節省對象XML列。我的想法是其他。我從鏈接中獲取代碼並將其更改爲通用IUserType實現。所以任何[Serializable]字段都可以保存在XML列中。

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) 
    { 
    } 
} 

用法與FluentNHibernate:

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(); 
    } 
    } 

也許這將幫助別人。

相關問題