• 实体类的枚举属性--原来支持枚举类型这么简单,没有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开源技术团队

    相关链接:

     
  • 相关阅读:
    HDU 5912 Fraction (模拟)
    CodeForces 722C Destroying Array (并查集)
    CodeForces 722B Verse Pattern (水题)
    CodeForces 722A Broken Clock (水题)
    CodeForces 723D Lakes in Berland (dfs搜索)
    CodeForces 723C Polycarp at the Radio (题意题+暴力)
    CodeForces 723B Text Document Analysis (水题模拟)
    CodeForces 723A The New Year: Meeting Friends (水题)
    hdu 1258
    hdu 2266 dfs+1258
  • 原文地址:https://www.cnblogs.com/bluedoctor/p/3252963.html
Copyright © 2020-2023  润新知