zoukankan      html  css  js  c++  java
  • 把Sql数据转换为业务数据的几种方法

    ORM系统必须把数据库中的数据转换为业务数据,转换的方法大致有3种,本文就试图对它们做一些简单分析。

    1、属性反射。就是通过反射,获取业务实体类的各个属性,然后再设置这些属性的值。这个方法最简单、最稳定、通用性最强、可维护性最强、性能最差。例如NHibernate就是用这种方法实现的,它通过IGetterISetter接口实现对某个业务实体类属性的读取和写入。DongLiORM的早期版本也是用的这种方法,他通过BusinessObject的属性索引器实现。其原理就是首先通过获取某个业务实体类某个属性的PropertyInfo,然后调用该PropertyInfoGetValue或者SetValue方法。类似的代码如下:

    PropertyInfo info = BusinessType.GetProperty(PropertyName);

    info.SetValue(this, value, null);

    比如,现在有一个业务实体类UserItem,其定义如下:

    public class UserItem

         {

            public UserItem() { }

            private string _userid;

            private string _username;

            private string _pwd;

            private string _email;

            public string UserID

            {

                set { _userid = value; }

                get { return _userid; }

            }

            public string UserName

            {

                set { _username = value; }

                get { return _username; }

            }

            public string Pwd

            {

                set { _pwd = value; }

                get { return _pwd; }

            }

            public string Email

            {

                set { _email = value; }

                get { return _email; }

       }

    }

    UserItem对应数据库中的Users表,他的属性对应Users表的字段UserIDUserNamePwdEmail。现有一个返回了Users表数据的IDataReader,要把IDataReader转换为一个UserItem的数组,就用类似如下的方法:

            public T[] DbReaderToBusinessObject<T>(IDataReader Reader) where T: new()

            {

                List<T> list = new List<T>();           

                while (Reader.Read())

                {

                    T Item = new T();               

                    Type BusinessType = Item.GetType();

                    for (int i = 0; i < Reader.FieldCount; i++)

                    {

                        string PropertyName = Reader.GetName(i);

                        PropertyInfo info = BusinessType.GetProperty(PropertyName);

                        info.SetValue(Item,Reader[i],null);

                    }

                    list.Add(Item);

                }

                Reader.Close();

                return list.ToArray();

     }

    2、通过XML序列化。就是在读取数据的时候,从数据库中返回的Xml形式的数据,然后通过用XmlSerializerDeserialize方法把数据转换成业务数据。目前没有见到有用这种方法实现的产品。其优点同第一种方法,但转换的效率似乎比第一种方法效率高一些(不过也不会高多少,反序列化实际上也需要反射),但是增加了从数据库中返回数据的数据量,而且对于已经编译了的业务实体类也无能为力。其实现方法类似下面的过程(以Sql Server 2000为例)。

       业务实体类的定义:

       [Serializable]

       [XmlRoot("Users")]

        public class UserItem

        {

            public UserItem(){}

            private string _userid;

            private string _username;

            private string _pwd;

            private string _email;

            [XmlAttribute("UserID")]

            public string UserID

            {

                set { _userid = value; }

                get { return _userid; }

            }

            [XmlAttribute("UserName")]

            public string UserName

            {

                set { _username = value; }

                get { return _username; }

            }

            [XmlAttribute("Pwd")]

            public string Pwd

            {

                set { _pwd = value; }

                get { return _pwd; }

            }     

            [XmlAttribute("Email")]

            public string Email

            {

                set { _email = value; }

                get { return _email; }

            }

       }

      转换过程:

       List<UserItem> UserList = new List<UserItem>();

       string XmlSql = "select * from Users for xml auto";

        SqlCommand cmd = new SqlCommand(XmlSql, con);

     cmd.CommandText = XmlSql;

        XmlReader r = cmd.ExecuteXmlReader();

        XmlSerializer sr = new XmlSerializer(typeof(UserItem));

        while (r.Read())

        {

            UserList.Add(sr.Deserialize(r) as UserItem);

        }

    r.Close();

    3、在业务实体类中自定义一个把Sql数据解析成业务数据的方法。这种方法的优点是转换的效率非常高,在理想的情况下,和Ado.net的速度不相上下,缺点是必须对每个业务实体类实现一个把Sql数据解析成业务数据的方法。手工编码的工作量非常大,配上专门的代码辅助工具,可以减轻工作量,但是,如果数据结构需要改动,则改动的地方比较多,容易出错。用这种方法实现的有NBear V3DongLiORM 1.2等。比如NBear V3中就有几个专门方法,比如:

    public override void SetPropertyValues(System.Data.IDataReader reader);

    public override void SetPropertyValues(System.Data.DataRow row);

     

    DongLiORM则是通过重写索引器(还是上文的UserItem)

    public override object this[string PropertyName]

         {

                get

                {

                    switch (PropertyName)

                    {

                        case "UserID": return _userid;

                        case "UserName": return _username;

                        case "Pwd": return _pwd;

                        case "Email": return _email;

                    }

                    return base[PropertyName];

                }

                set

                {

                    switch (PropertyName)

                    {

                        case "UserID": _userid = (string)value; return;

                        case "UserName": _username = (string)value; return;

                        case "Pwd": _pwd = (string)value; return;

                        case "Email": _email = (string)value; return;

                    }

                    base[PropertyName] = value;

                }

    }

     

    “鱼我所欲也,熊掌亦我所欲也,二者不可得兼,舍鱼而取熊掌者也”。系统的性能和代码简单性,二者不可兼得,到底我们更需要谁呢?

     

    狂想:假设我们有一个这样的东西,他能够在运行时候改变现有的某个类(比如UserItem)的某个属性(比如索引器)/方法(比如SetPropertyValues)就好了,这样我们就可以在设计的时候写非常少的代码,而又能够获得比较高的运行效率。可惜PropertyBuilder等只能对动态类有用,帮不上忙。

     

    我所想到方法的就这些,各有优点和缺点,不知各位有没有其他的方法,能让统的性能和代码简单性和谐统一。

    原贴地址:http://www.cnblogs.com/Yahong111/archive/2007/07/27/833028.html

  • 相关阅读:
    kafka集群搭建
    数据导入 xls --》mysql
    Spark --RDD算子
    Spark集群搭建
    【已解决】 IDEA运行spark程序报错:GC overhead limit exceeded?
    Spring Boot 配置 ---02
    Spring Boot 入门 ---01
    Nginx 推流 拉流 --- 点播直播
    【转】JS内置对象方法
    MapReduce 简单数据统计
  • 原文地址:https://www.cnblogs.com/zhuawang/p/2142825.html
Copyright © 2011-2022 走看看