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

    public enum RoleNames
{
User,
Manager,
Admin
}

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

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

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

//获取一个实体类:
Users user=new Users();
user.ID=; 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(, , );
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, ); }
} /// <summary>
///
/// </summary>
public System.String Password
{
get { return getProperty<System.String>("Password"); }
set { setProperty("Password", value, ); }
} /// <summary>
///
/// </summary>
public System.String NickName
{
get { return getProperty<System.String>("NickName"); }
set { setProperty("NickName", value, ); }
} /// <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, ); }
} /// <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, ); }
} /// <summary>
///
/// </summary>
public System.String Remarks
{
get { return getProperty<System.String>("Remarks"); }
set { setProperty("Remarks", value, ); }
} /// <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 \r\n{0}", q0);
Console.WriteLine(q0.PrintParameterInfo()); var userList= EntityQuery<Users>.QueryList(q0);
if (userList.Count > )
{
Users u = userList[];
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开源技术团队

相关链接:

 

实体类的枚举属性--原来支持枚举类型这么简单,没有EF5.0也可以的更多相关文章

  1. 尚硅谷面试第一季-11MyBatis中当实体类中的属性名和表中的字段名不一样怎么办

    问题: MyBatis中当实体类中的属性名和表中的字段名不一样 ,怎么办 ? 解决方案: 1.写sql语句时起别名 <!-- id属性:必须是接口中方法的方法名 resultType属性:必须是 ...

  2. java中遍历实体类,获取属性名和属性值

    方式一(实体类): //java中遍历实体类,获取属性名和属性值 public static void testReflect(Object model) throws Exception{ for ...

  3. mybatis中实体类跟数据库属性不一致解决方案

    1.在Mapper.xml映射配置文件中给sql语句起别名 select id as uid,username as name from user 2.mybatis中可以单独的配置查询结果的列名和实 ...

  4. Java使用PropertyDescriptor获取实体类中私有属性的值,并给私有属性赋值

    大家都知道Java类中的私有的(private)属性是获取不到的(即使使用继承依然获取不到),那如果非要获取私有属性的值怎么办呢?一般的做法是将该java类封装称为一个JavaBean,即封装该私有属 ...

  5. 你是否有遇到过某个实体类字段(属性)过多的情况,不想每次点的话戳进来(C# 反射)

    贴上一段代码: bureaucraticEntities apply = new bureaucraticEntities(); Type tapp= app.GetType(); Type ttmp ...

  6. EF实体类指定部分属性不映射数据库标记

    命名空间 ;using System.ComponentModel.DataAnnotations.Schema; 实体部分 public partial class Student { [NotMa ...

  7. resultMap自定义映射---8.3.1. 解决列名(表中的字段名称)和实体类中的属性名不一致

    1.1.1.1.      步骤一:将驼峰匹配注释掉 --------------测试完成后仍然 回来开启  其他地方可能用到 一旦注释掉驼峰匹配,那么再通过queryUserById查询的结果中,用 ...

  8. EF 实体类的制定属性不生成数据库字段

    添加一个标签即可 [NotMapped] 没什么营养,就是防忘记

  9. EF实体类指定部分属性不映射成数据库字段特性

    添加NotMapped 特性 /// <summary> /// 用户名 /// </summary> [NotMapped] public string user_name ...

随机推荐

  1. mysql创建数据库

    mysql创建数据库 创建utf8编码的数据库 CREATE DATABASE IF NOT EXISTS my_db default character set utf8 COLLATE utf8_ ...

  2. 如何解决loadrunner回放日志中的乱码问题

    在Loadrunner回放脚本时,会看到replay log区会展示脚本回放时的信息.有时候选中了打印服务器返回具体信息后,服务器返回的中文字符为乱码.怎么破? 原来Loadrunner的replay ...

  3. 利用JSDOC快速生成注释文档,非常棒。

    有时往往我们需要建一个文档来记录js中的一些代码注释,比如一些公共的函数,又或者一些类,在团队合作中,文档接口也是必不可少的,传统的方式多少有些不便,这里介绍一个工具,它叫JSDOC,它可以用来将注释 ...

  4. 各浏览器Iframe对contentWindow、contentDocument、document及frames属性测试

    Iframe易于嵌套及管理页面,但经常遇到跨域.父子页面访问问题,对于子页面访问父页面可以兼容性地通过window.Top或window.Parent或window.frameElement等操作,但 ...

  5. java中有关线程的题目

    1,看一下下面程序错误发生在哪一行! class Test implements Runnable{ public void run(Thread t){ } } 2,输出结果是什么? class T ...

  6. Uvaoj10054 - The Necklace

    /* 题意:打印欧拉回路! 思路:开始时不明白,dfs为什么是后序遍历? 因为欧拉回路本身是一条回路,那么我们在dfs时,可能存在提前找到回路,这条回路可能不是欧拉回路, 因为没有遍历完成所有的边!如 ...

  7. python--基础学习(二)判断 、循环、定义函数、继承、调用

    1.判断 if.elif 代码示范 # coding=utf-8 score = 90 if (score>=90): print("完美") print("优秀& ...

  8. bootstrap-datetimepicker.js学习

    之前项目运用到了这个时间控件,期间bug还是一些.抽个时间,简单地看一下. 先看一下datetimepicker.js的结构 var DateTimePicker = function(element ...

  9. 邻接矩阵无向图(三)之 Java详解

    前面分别介绍了邻接矩阵无向图的C和C++实现,本文通过Java实现邻接矩阵无向图. 目录 1. 邻接矩阵无向图的介绍 2. 邻接矩阵无向图的代码说明 3. 邻接矩阵无向图的完整源码 转载请注明出处:h ...

  10. Anliven - 你的学习为何如此低效?!

    拖延 适时学习的本质就是营造机会,具有强烈的时效性,而拖延能够毁灭所有机会! 一个得不到执行的完美计划,比不上一次仓促的执行! 盲目 缺少有效的策略和方法,没有弄清基本的问题(需求--->性质- ...