2012-04-04 13 views
5

Mam poniższej tabeli:Jak odwzorować kolumnę typu XML na mocno wpisaną właściwość obiektu za pomocą NHibernate?

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

muszę mapować go do obiektu:

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

Gdzie, StronglyTypedData jest coś takiego:

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

Domyślnie, kolumny XML są odwzorowane na właściwości XmlDocument, ale chciałbym, aby w czasie odwzorowywania wystąpiła serializacja/deserializacja XML na właściwość StronglyTypedData.

Co muszę zrobić, aby to osiągnąć?

Odpowiedz

4

Musisz napisać IUserType, który zajmuje się konwersją.

Można zacząć od XmlDocType, która jest faktycznie konwertująca z surowego XML do XmlDocument.

+0

Jedno wiem Chcę uniknąć używania XmlDocument. To brzmi jak niepotrzebne obciążenie. Wolałbym serializować/deserializować bezpośrednio pomiędzy surowym XML a silnie wpisanymi obiektami, tj. Użyć XmlSerializatora zamiast XmlDoc. – tishma

+1

Sugeruję, abyś spojrzał na XmlDocType ** jako przykład **, ponieważ twoja implementacja będzie podobna. –

+0

Rozumiem. Zobaczę. Dzięki. – tishma

8

Miałem zamiar zrobić to komentarz do posta Diego, ale było to za długie i chciałem podświetlanie składni. Zmodyfikowałem typ XmlDocType, który opublikował Diego, aby używał serializacji xml do iz mocno wpisanego obiektu.

zrobiłem własną rodzajowe IUserType do obsługi silne wpisując:

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

} 

w końcu, można użyć Fluent.NHibernate odwzorować kolumny tak:

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

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

Stary, jesteś ratownikiem! –

Powiązane problemy