我可以使用NHibernate以xml序列化形式存储对象吗?

时间:2009-04-30 16:51:38

标签: nhibernate serialization

说我有这样的课程:

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:2)

我有同样的想法将对象保存在XML列中。我的想法是其他的。我从链接中获取代码并将其更改为通用IUserType实现。因此,[Serializable]的任何字段/ prop都可以保存在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();
    }
  }

也许它会帮助某人。