zoukankan      html  css  js  c++  java
  • 实体类的枚举属性--原来支持枚举类型这么简单,没有EF5.0也可以

        通常,我们都是在业务层和界面层使用枚举类型,这能够为我们编程带来便利,但在数据访问层,不使用枚举类型,因为很多数据库都不支持,比如我们现在用的SqlServer2008就不支持枚举类型的列,用的时候也是将枚举类型转换成int 类型,数据库存储的是int 类型的数据,在访问数据的时候进行枚举类型和int类型的转换,例如下面的例子:

        public enum RoleNames
        { 
            User,
            Manager,
            Admin
        }

    假设有一个实体类Users,如果实体类不支持枚举类型,得这样使用(下面的示例都以PDF.NET的ORM框架使用来说明):

    //获取一个实体类:
    Users user=new Users();
    user.ID=1;
    
    if(EntityQuery<Users>.Fill(user))
    {
     RoleNames rn=(RoleNames)user.RoleID;
     Console.Write("Role Name:"+rn);
    }
    
    
    //更新实体类:
    Users user=new Users();
    user.ID=1;
    user.RoleID=(int)RoleNames.Admin;
    EntityQuery<Users>.Instance.Update(user);

        查询和更新操作都得对枚举类型进行转换,不方便,虽然如此,我们大部分情况下还是将就了,在访问数据库的时候这么转换下。这种情况下EF 5.0 之前也不例外,都是社区用户的强烈要求,在EF5.0版本之后才加入支持实体类枚举属性的。

        既然使用枚举还要将实体类的属性转换下,为何不直接将实体类的属性定义成枚举类型?
        修改下Users类型的定义:

    public partial class Users : EntityBase
    {
            //其它部分定义略
    
            public RoleNames RoleID
            {
                get { return getProperty<RoleNames>("RoleID"); }
                set { setProperty("RoleID", value); }
            }
    
    }

    直接使用这个修改过的实体类来插入、修改数据,是没有问题的:

    //更新实体类:
    Users user=new Users();
    user.ID=1;
    user.RoleID=RoleNames.Admin;
    EntityQuery<Users>.Instance.Update(user);

    但是查询实体类的时候会有点小问题,虽然能够正确的从数据库查询,但查看枚举属性的时候会报类型转换错误:

    //获取一个实体类:
    Users user=new Users();
    user.ID=1;
    
    if(EntityQuery<Users>.Fill(user))
    {
     RoleNames rn=user.RoleID;
     Console.Write("Role Name:"+rn);
    }

        跟踪代码发现,user.RoleID 对应的SqlReader 的结果类型是int ,因为数据库的RoleID 列没法定义成枚举类型,如果要将实体类的属性定义成枚举类型,那么在SqlReader读取的时候,必须进行类型转换:

    user.RoleID=(RoleNames)reader["RoleID"];

        幸好PDF.NET的实体类认为“实体类是数据的容器”,内部采用一个object[] 保存来自数据库的原始数据,而在使用数据的时候,才来进行类型转换,因此框架原来查询数据、插入、更新数据的地方,都不用做任何修改,只需要修改下 getProperty<T>("fieldName") 涉及的部分:

           public static T ChangeType<T>(object Value)
           {
               if (Value is T)
                   return (T)Value;
               else if (Value == DBNull.Value || Value == null)
               {
                   if (typeof(T) == typeof(DateTime))
                   {
                       //如果取日期类型的默认值 0001/01/01 ,在WCF JSON序列化的时候,会失败。
                       object o = new DateTime(1900, 1, 1);
                       return (T)o;
                   }
                   else
                       return default(T);
               }
               else
               {
                   //edit at 2011.5.16
                   //如果 Value为 decimal类型,T 为double 类型, (T)Value 将发生错误
                   //edit at 2013.8.9 支持枚举类型
                   if (typeof(T).IsEnum)
                       return (T)Value;
                   else
                       return (T)Convert.ChangeType(Value, typeof(T));
               }
           }

    使用PDF.NET框架的V4.X 版本(包括V4.6之前的版本)用户,只需要打开 CommonUtil.cs 文件,找到该方法,将

    return (T)Convert.ChangeType(Value, typeof(T));

    修改为:

     if (typeof(T).IsEnum)
           return (T)Value;
     else
           return (T)Convert.ChangeType(Value, typeof(T));

    即可。


        经过测试,通过这样的修改,框架就可以支持实体类使用枚举类型了。


        为什么修改如此简单?前面已经说过,PDF.NET的实体类是数据的容器,也就是说,我们在内存中将某个属性的值直接设置为枚举类型的值,也可以将内存中的Int 类型的来自数据库的值,在运行时转换成枚举类型。这样,使得PDF.NET的实体类的属性类型可以不必跟数据库的字段类型严格对应,只要类型相容即可。这个特点为系统移植数据库平台提供了很大的便利,比如Oracle 没有Decimal类型,没有real 类型,要使用非整形的数字类型,只有使用Number类型,那么为SqlServer设计使用的实体类,一般情况下也可以直接在Oracle下使用。

        下面的代码是一个完整的使用实体类的枚举属性的例子:

    using System;
    using System.Collections.Generic;
    //using System.Linq;
    using System.Text;
    using PWMIS.DataMap.Entity;
    using PWMIS.Common;
    
    namespace OQLTest
    {
        public enum RoleNames
        { 
            User,
            Manager,
            Admin
        }
        public partial class Users : EntityBase
        {
            public Users()
            {
                TableName = "LT_Users";
                EntityMap = EntityMapType.Table;
                //IdentityName = "标识字段名";
                IdentityName = "ID";
    
                //PrimaryKeys.Add("主键字段名");
                PrimaryKeys.Add("ID");
    
    
            }
    
    
            protected override void SetFieldNames()
            {
                PropertyNames = new string[] { "ID", "UserName", "Password", "NickName", "RoleID", "Authority", "IsEnable", "LastLoginTime", "LastLoginIP", "Remarks", "AddTime" };
            }
    
    
    
            /// <summary>
            /// 
            /// </summary>
            public System.Int32 ID
            {
                get { return getProperty<System.Int32>("ID"); }
                set { setProperty("ID", value); }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public System.String UserName
            {
                get { return getProperty<System.String>("UserName"); }
                set { setProperty("UserName", value, 50); }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public System.String Password
            {
                get { return getProperty<System.String>("Password"); }
                set { setProperty("Password", value, 50); }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public System.String NickName
            {
                get { return getProperty<System.String>("NickName"); }
                set { setProperty("NickName", value, 50); }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public RoleNames RoleID
            {
                get { return getProperty<RoleNames>("RoleID"); }
                set { setProperty("RoleID", value); }
            }
    
            //用下面的方式处理实体类的子实体类问题
            UserRoles _roles;
            public UserRoles Roles
            {
                get
                {
                    if (_roles == null)
                    {
                        _roles = new UserRoles() { ID = this.RoleID };
                        EntityQuery<UserRoles>.Fill(_roles);
                    }
                    return _roles;
                }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public System.String Authority
            {
                get { return getProperty<System.String>("Authority"); }
                set { setProperty("Authority", value, 250); }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public System.Boolean IsEnable
            {
                get { return getProperty<System.Boolean>("IsEnable"); }
                set { setProperty("IsEnable", value); }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public System.DateTime LastLoginTime
            {
                get { return getProperty<System.DateTime>("LastLoginTime"); }
                set { setProperty("LastLoginTime", value); }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public System.String LastLoginIP
            {
                get { return getProperty<System.String>("LastLoginIP"); }
                set { setProperty("LastLoginIP", value, 20); }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public System.String Remarks
            {
                get { return getProperty<System.String>("Remarks"); }
                set { setProperty("Remarks", value, 150); }
            }
    
            /// <summary>
            /// 
            /// </summary>
            public System.DateTime AddTime
            {
                get { return getProperty<System.DateTime>("AddTime"); }
                set { setProperty("AddTime", value); }
            }
    
        }
    
    }
    用户实体类定义

        测试程序:

                Users user = new Users() { NickName = "pdf.net", RoleID= RoleNames.Admin };
             
                OQL q0 = OQL.From(user)
                   .Select()
                   .Where(user.NickName, user.RoleID) 
                   .OrderBy(user.ID)
                   .END;
                q0.SelectStar = true;
                Console.WriteLine("q0:one table and select all fields 
    {0}", q0);
                Console.WriteLine(q0.PrintParameterInfo());
    
                var userList= EntityQuery<Users>.QueryList(q0);
                if (userList.Count > 0)
                {
                    Users u = userList[0];
                    Console.WriteLine("User Type is:"+u.RoleID.ToString());
                    u.RoleID = RoleNames.User;
                    EntityQuery<Users>.Instance.Update(u);
                }

        程序输出:

        数据库结果界面:

    --------------分界线----------------------

    PDF.NET 开发框架是国产的开发框架,支持SQL-MAP、ORM和数据控件 三种编程模型,可以一种或者三种混合使用,是开源的开发框架,供广大.net开发朋友在EF,NH之外,提供第三中选择。欢迎加入PDF.NET开源技术团队

    相关链接:

     
  • 相关阅读:
    Python自学之路-面试题
    k8s学习笔记之三:configmap和secret
    k8s学习笔记之二:Pod
    k8s学习笔记之四:使用kubeadm配置Ingress
    k8s学习笔记之一:使用kubeadm安装k8s集群
    HTTP content-type
    Json对象和Json字符串的区别
    .net 5+ 知新:【2】 .Net Framework 、.Net 、 .NET Standard的概念与区别
    Log4net和Nlog
    通过系统存储过程手动执行SQL Server中的Job
  • 原文地址:https://www.cnblogs.com/bluedoctor/p/3252963.html
Copyright © 2011-2022 走看看