2009-04-30 83 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(); 
    } 
    } 

也许这将帮助别人。

相关问题