2012-04-04 161 views
5

我有以下表格:如何使用NHibernate將XML類型列映射到強類型對象屬性?

CREATE TABLE [dbo].[Data] (
    [Id]   UNIQUEIDENTIFIER NOT NULL, 
    [Data] XML    NOT NULL, 
); 

我需要將其映射到對象:

class Data 
{ 
    public virtual Guid Id {get; set;} 
    public virtual StronglyTypedData Data {get; set;} 
} 

其中,StronglyTypedData是一樣的東西:

class StronglyTypedData 
{ 
    public string Name {get; set;} 
    public int Number {get; set;} 
} 

默認情況下,XML列被映射到XmlDocument屬性,但是我希望XML序列化/反序列化到StronglyTypedData屬性,而不是在映射時發生。

我需要做些什麼才能做到這一點?

回答

4

您需要編寫一個負責轉換的IUserType

您可以從XmlDocType開始,這是實際從原始XML轉換爲XmlDocument的人。

+0

有一件事我知道我想避免使用XmlDocument。這聽起來像是不必要的開銷。我寧願直接在原始XML和強類型對象之間序列化/反序列化,即使用XmlSerializator而不是XmlDoc。 – tishma 2012-04-04 13:17:57

+1

我建議你看看XmlDocType **作爲例子**,因爲你的實現將會類似。 – 2012-04-04 13:19:24

+0

我明白了。我會看看。謝謝。 – tishma 2012-04-04 13:23:36

8

我打算對迭戈的帖子發表評論,但它太長了,我想要語法突出顯示。我修改了Diego發佈的XmlDocType,以便它使用xml序列化來自和強類型對象。

我做我自己的通用IUserType處理強類型:

//you'll need these at the top of your file 
//using System; 
//using System.Collections.Generic; 
//using System.Linq; 
//using System.Text; 
//using NHibernate.UserTypes; 
//using NHibernate.SqlTypes; 
//using System.Data; 
//using System.Xml; 
//using NHibernate.Type; 

[Serializable] 
public class XmlType<T> : MutableType 
{ 
    public XmlType() 
     : base(new XmlSqlType()) 
    { 
    } 


    public XmlType(SqlType sqlType) 
     : base(sqlType) 
    { 
    } 

    public override string Name 
    { 
     get { return "XmlOfT"; } 
    } 

    public override System.Type ReturnedClass 
    { 
     get { return typeof(T); } 
    } 

    public override void Set(IDbCommand cmd, object value, int index) 
    { 
     ((IDataParameter)cmd.Parameters[index]).Value = XmlUtil.ConvertToXml(value); 
    } 

    public override object Get(IDataReader rs, int index) 
    { 
     // according to documentation, GetValue should return a string, at list for MsSQL 
     // hopefully all DataProvider has the same behaviour 
     string xmlString = Convert.ToString(rs.GetValue(index)); 
     return FromStringValue(xmlString); 
    } 

    public override object Get(IDataReader rs, string name) 
    { 
     return Get(rs, rs.GetOrdinal(name)); 
    } 

    public override string ToString(object val) 
    { 
     return val == null ? null : XmlUtil.ConvertToXml(val); 
    } 

    public override object FromStringValue(string xml) 
    { 
     if (xml != null) 
     { 
      return XmlUtil.FromXml<T>(xml); 
     } 
     return null; 
    } 

    public override object DeepCopyNotNull(object value) 
    { 
     var original = (T)value; 
     var copy = XmlUtil.FromXml<T>(XmlUtil.ConvertToXml(original)); 
     return copy; 
    } 

    public override bool IsEqual(object x, object y) 
    { 
     if (x == null && y == null) 
     { 
      return true; 
     } 
     if (x == null || y == null) 
     { 
      return false; 
     } 
     return XmlUtil.ConvertToXml(x) == XmlUtil.ConvertToXml(y); 
    } 
} 

//the methods from this class are also available at: http://blog.nitriq.com/PutDownTheXmlNodeAndStepAwayFromTheStringBuilder.aspx 
public static class XmlUtil 
{ 
    public static string ConvertToXml(object item) 
    { 
     XmlSerializer xmlser = new XmlSerializer(item.GetType()); 
     using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) 
     { 
      xmlser.Serialize(ms, item); 
      UTF8Encoding textconverter = new UTF8Encoding(); 
      return textconverter.GetString(ms.ToArray()); 
     } 
    } 

    public static T FromXml<T>(string xml) 
    { 
     XmlSerializer xmlser = new XmlSerializer(typeof(T)); 
     using (System.IO.StringReader sr = new System.IO.StringReader(xml)) 
     { 
      return (T)xmlser.Deserialize(sr); 
     } 
    } 

} 

然後,最後,您可以使用Fluent.NHibernate你列映射這樣的:

public partial class MyTableEntityMap: ClassMap<MyTableEntity> 
{ 
    public MyTableEntityMap() 
    { 
     Table("MyTable"); 
     //... 

     Map(x => x.MyStronglyTypedProperty).Column("SomeXmlTypeSqlColumn").CustomType(typeof(XmlType<TypeOfMyProperty>)); 
    } 
} 
+0

老兄,你是一個救星! – 2015-12-02 12:11:39

相關問題