2012-04-04 30 views
5

Tôi đã theo bảng dưới đây:Làm thế nào để ánh xạ cột loại XML thành một thuộc tính đối tượng được gõ mạnh mẽ với NHibernate?

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

tôi cần để ánh xạ nó vào đối tượng:

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

đâu, StronglyTypedData là một cái gì đó như:

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

Theo mặc định, các cột XML được ánh xạ tới các thuộc tính XmlDocument, nhưng tôi muốn tuần tự hóa XML/deserialization thành thuộc tính StronglyTypedData xảy ra thay vào thời gian ánh xạ.

Tôi cần làm gì để thực hiện việc này?

Trả lời

4

Bạn cần viết IUserType để đảm nhiệm chuyển đổi.

Bạn có thể bắt đầu từ XmlDocType, thực tế là chuyển đổi từ XML thô thành XmlDocument.

+0

Một điều tôi biết Tôi muốn tránh sử dụng XmlDocument. Nghe có vẻ như một chi phí không cần thiết. Tôi muốn serialize/deserialize trực tiếp giữa XML thô và các đối tượng được gõ mạnh, tức là sử dụng XmlSerializator thay vì XmlDoc. – tishma

+1

Tôi đề nghị bạn xem XmlDocType ** như một ví dụ **, bởi vì việc triển khai của bạn sẽ tương tự. –

+0

Tôi hiểu. Tôi sẽ có một cái nhìn. Cảm ơn. – tishma

8

Tôi sẽ làm cho nhận xét này trên bài đăng của Diego, nhưng nó quá dài và tôi muốn làm nổi bật cú pháp. Tôi đã sửa đổi XmlDocType mà Diego đã đăng để nó sử dụng xml serialization đến và từ một đối tượng được đánh máy mạnh.

tôi đã IUserType generic của riêng tôi để xử lý các gõ mạnh:

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

} 

Sau đó, cuối cùng, bạn có thể sử dụng để lập bản đồ Fluent.NHibernate cột của bạn như thế này:

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

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

Dude, bạn là một phao cứu sinh! –

Các vấn đề liên quan