数据库中的 NHibernate XML 文档到实体中的 Expando 对象

发布于 2024-09-27 04:46:57 字数 181 浏览 6 评论 0原文

我有一个包含 xml 列的 SQL Server 数据库。我需要将该 xml 列映射到我的域实体中的 Expando 对象。我正在使用 NHibernate。我如何扩展 NHibernate 来适应这种情况?我假设(我是 NHibernate 的新手)我必须重写实现来获取和设置 xml 数据,但我不知道如何在 NHibernate 中做到这一点。

I have a SQL Server database that contains an xml column. I need to map that xml column to an expando object within my domain entity. I am using NHibernate. How do I extend NHibernate to accommodate this? I am assuming (I am new to NHibernate) that I have to override the implementation to get and set the xml data, but I don't know how to do that in NHibernate.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

虚拟世界 2024-10-04 04:46:57

You have to create custom type (IUserType) for your entity. Here there is a nice article how to transform XML column from database to a NHibernate domain entity.

热情消退 2024-10-04 04:46:57

感谢 Petr 的回答,我对用户类型进行了以下初步尝试来处理扩展。它工作得很好,我现在可以为每个对象提供客户端设置属性。我设置了每个对象必须具有的属性,然后每个客户端都可以添加自己的属性来满足自己的需求。

需要注意的是 - 我只是为了持久性目的而设置它。在此应用程序中不需要搜索,因为所有查询都是针对具有非规范化数据副本的 MongoDB 数据库完成的。

public class ExpandoUserType : IUserType
{
    public object Assemble(object cached, object owner)
    {
        return cached;
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Disassemble(object value)
    {
        return value;
    }

    public bool Equals(object x, object y)
    {
        return false;
    }

    public int GetHashCode(object x)
    {
        return 0;
    }

    public bool IsMutable
    {
        get { return false; }
    }

    public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
    {
        var obj = NHibernateUtil.XmlDoc.NullSafeGet(rs, names[0]);

        if (obj == null) return null;

        var xmldoc = (XmlDocument)obj;

        dynamic expando = new ExpandoObject();

        foreach (XmlElement el in xmldoc.FirstChild.ChildNodes)
        {
            object val = null;

            switch (Convert.ToString(el.Attributes["type"].InnerText).ToLower())
            {
                case "string":
                    val = el.InnerText;
                    break;

                case "int32":
                    val = Convert.ToInt32(el.InnerText);
                    break;

                case "int16":
                    val = Convert.ToInt16(el.InnerText);
                    break;

                case "int64":
                    val = Convert.ToInt64(el.InnerText);
                    break;

                case "bool":
                    val = Convert.ToBoolean(el.InnerText);
                    break;

                case "datetime":
                    val = Convert.ToDateTime(el.InnerText);
                    break;

                case "byte":
                    val = Convert.ToByte(el.InnerText);
                    break;

                case "decimal":
                    val = Convert.ToDecimal(el.InnerText);
                    break;
            }
            ((IDictionary<String, Object>)expando).Add(el.Name, val);
        }

        return expando;

    }

    /// <summary>
    /// Transforms the expando object to an XML Document for storage in SQL.
    /// </summary>
    /// <param name="cmd"></param>
    /// <param name="value"></param>
    /// <param name="index"></param>
    public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)
    {
        if (value == null || value == DBNull.Value)
        {
            NHibernateUtil.String.NullSafeSet(cmd, null, index);
        }
        else
        {
            NHibernateUtil.XmlDoc.Set(cmd, expandoToXML((ExpandoObject) value, "root"), index);
        }
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public Type ReturnedType
    {
        get { return typeof(ExpandoObject); }
    }

    public NHibernate.SqlTypes.SqlType[] SqlTypes
    {
        get { return new[] { NHibernateUtil.XmlDoc.SqlType };  }
    }


    private static XmlDocument expandoToXML(dynamic node, String nodeName)
    {
        XElement xmlNode = new XElement(nodeName);

        foreach (var property in (IDictionary<String, Object>)node)
        {

            if (property.Value.GetType() == typeof(ExpandoObject))
                xmlNode.Add(expandoToXML(property.Value, property.Key));

            else
                if (property.Value.GetType() == typeof(List<dynamic>))
                    foreach (var element in (List<dynamic>)property.Value)
                        xmlNode.Add(expandoToXML(element, property.Key));
                else
                {
                    XElement xnode = new XElement(property.Key, property.Value);
                    xnode.SetAttributeValue("type", property.Value.GetType().Name);
                    xmlNode.Add(xnode);
                }
        }

        return xmlNode.GetXmlNode();
    }
}

Thanks to Petr's answer, I have come up with the following initial attempt at a user type to handle the expando. It works quite nicely and I can now offer client set properties for each of my objects. I set the properties that each object must have, and each client can then add their own properties to meet their needs.

One caveat - I am only setting this up for persistence purposes. Searching is not necessary in this app as all querying is done against a MongoDB database that has denormalized copies of the data.

public class ExpandoUserType : IUserType
{
    public object Assemble(object cached, object owner)
    {
        return cached;
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Disassemble(object value)
    {
        return value;
    }

    public bool Equals(object x, object y)
    {
        return false;
    }

    public int GetHashCode(object x)
    {
        return 0;
    }

    public bool IsMutable
    {
        get { return false; }
    }

    public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
    {
        var obj = NHibernateUtil.XmlDoc.NullSafeGet(rs, names[0]);

        if (obj == null) return null;

        var xmldoc = (XmlDocument)obj;

        dynamic expando = new ExpandoObject();

        foreach (XmlElement el in xmldoc.FirstChild.ChildNodes)
        {
            object val = null;

            switch (Convert.ToString(el.Attributes["type"].InnerText).ToLower())
            {
                case "string":
                    val = el.InnerText;
                    break;

                case "int32":
                    val = Convert.ToInt32(el.InnerText);
                    break;

                case "int16":
                    val = Convert.ToInt16(el.InnerText);
                    break;

                case "int64":
                    val = Convert.ToInt64(el.InnerText);
                    break;

                case "bool":
                    val = Convert.ToBoolean(el.InnerText);
                    break;

                case "datetime":
                    val = Convert.ToDateTime(el.InnerText);
                    break;

                case "byte":
                    val = Convert.ToByte(el.InnerText);
                    break;

                case "decimal":
                    val = Convert.ToDecimal(el.InnerText);
                    break;
            }
            ((IDictionary<String, Object>)expando).Add(el.Name, val);
        }

        return expando;

    }

    /// <summary>
    /// Transforms the expando object to an XML Document for storage in SQL.
    /// </summary>
    /// <param name="cmd"></param>
    /// <param name="value"></param>
    /// <param name="index"></param>
    public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)
    {
        if (value == null || value == DBNull.Value)
        {
            NHibernateUtil.String.NullSafeSet(cmd, null, index);
        }
        else
        {
            NHibernateUtil.XmlDoc.Set(cmd, expandoToXML((ExpandoObject) value, "root"), index);
        }
    }

    public object Replace(object original, object target, object owner)
    {
        return original;
    }

    public Type ReturnedType
    {
        get { return typeof(ExpandoObject); }
    }

    public NHibernate.SqlTypes.SqlType[] SqlTypes
    {
        get { return new[] { NHibernateUtil.XmlDoc.SqlType };  }
    }


    private static XmlDocument expandoToXML(dynamic node, String nodeName)
    {
        XElement xmlNode = new XElement(nodeName);

        foreach (var property in (IDictionary<String, Object>)node)
        {

            if (property.Value.GetType() == typeof(ExpandoObject))
                xmlNode.Add(expandoToXML(property.Value, property.Key));

            else
                if (property.Value.GetType() == typeof(List<dynamic>))
                    foreach (var element in (List<dynamic>)property.Value)
                        xmlNode.Add(expandoToXML(element, property.Key));
                else
                {
                    XElement xnode = new XElement(property.Key, property.Value);
                    xnode.SetAttributeValue("type", property.Value.GetType().Name);
                    xmlNode.Add(xnode);
                }
        }

        return xmlNode.GetXmlNode();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文