2012-04-04 10 views
5

मैं है निम्न तालिका:एनएचबीर्नेट के साथ दृढ़ता से टाइप की गई ऑब्जेक्ट प्रॉपर्टी में एक्सएमएल टाइप कॉलम को कैसे मैप करें?

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

मैं वस्तु के लिए यह मैप करने की आवश्यकता:

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

डिफ़ॉल्ट रूप से, एक्सएमएल कॉलम:

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

कहाँ, StronglyTypedData कुछ की तरह है XmlDocument गुणों के लिए मैप किए गए हैं, लेकिन मैं एक्सएमएल क्रमबद्धता/deserialization स्ट्रिंगली टाइपेडडेटा संपत्ति के बजाय मैपिंग समय पर होने के लिए करना चाहता हूं।

इसे पूरा करने के लिए मुझे क्या करने की ज़रूरत है?

उत्तर

4

आपको IUserType लिखने की आवश्यकता है जो रूपांतरण की देखभाल करता है।

आप XmlDocType से शुरू कर सकते हैं, जो वास्तव में कच्चे एक्सएमएल से एक्सएमएल डॉक्यूमेंट में परिवर्तित हो रहा है।

+0

एक बात मुझे पता है मैं XmlDocument का उपयोग कर बचाना चाहता हूं। यह एक अनावश्यक ओवरहेड की तरह लगता है। मैं सीधे कच्चे एक्सएमएल और दृढ़ता से टाइप की गई वस्तुओं के बीच क्रमबद्ध/deserialize करना पसंद करेंगे, यानी XmlDoc के बजाय XmlSerializator का उपयोग करें। – tishma

+1

मैं सुझाव देता हूं कि आप XmlDocType ** को एक उदाहरण ** के रूप में देखें, क्योंकि आपका कार्यान्वयन कुछ समान होगा। –

+0

मैं देखता हूं। मैं एक बार नजर डालूँगा। धन्यवाद। – tishma

8

मैं डिएगो की पोस्ट पर यह टिप्पणी करने जा रहा था, लेकिन यह बहुत लंबा था और मैं वाक्यविन्यास को हाइलाइट करना चाहता था। मैंने XmlDocType को संशोधित किया है कि डिएगो ने पोस्ट किया है ताकि यह दृढ़ता से टाइप की गई वस्तु से और एक्सएमएल क्रमिकरण का उपयोग करेगा।

मैं मजबूत टाइपिंग को संभालने के लिए अपने ही सामान्य 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

दोस्त, आप एक lifesaver हैं! –