java 枚举值可以放空值么,怎么放

实体类的枚举属性--原来支持枚举类型这么简单,没有EF5.0也可以 - 深蓝医生 - 博客园
随笔 - 189, 文章 - 1, 评论 - 2053, 引用 - 0
&&& 通常,我们都是在业务层和界面层使用枚举类型,这能够为我们编程带来便利,但在数据访问层,不使用枚举类型,因为很多数据库都不支持,比如我们现在用的SqlServer2008就不支持枚举类型的列,用的时候也是将枚举类型转换成int 类型,数据库存储的是int 类型的数据,在访问数据的时候进行枚举类型和int类型的转换,例如下面的例子:
public enum RoleNames
假设有一个实体类Users,如果实体类不支持枚举类型,得这样使用(下面的示例都以的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.A
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.A
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)V
else if (Value == DBNull.Value || Value == null)
if (typeof(T) == typeof(DateTime))
//如果取日期类型的默认值
,在WCF JSON序列化的时候,会失败。
object o = new DateTime(1900, 1, 1);
return (T)o;
return default(T);
//如果 Value为 decimal类型,T 为double 类型, (T)Value 将发生错误
支持枚举类型
if (typeof(T).IsEnum)
return (T)V
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)V
return (T)Convert.ChangeType(Value, typeof(T));
&&& 经过测试,通过这样的修改,框架就可以支持实体类使用枚举类型了。
&&& 为什么修改如此简单?前面已经说过,PDF.NET的实体类是数据的容器,也就是说,我们在内存中将某个属性的值直接设置为枚举类型的值,也可以将内存中的Int 类型的来自数据库的值,在运行时转换成枚举类型。这样,使得PDF.NET的实体类的属性类型可以不必跟数据库的字段类型严格对应,只要类型相容即可。这个特点为系统移植数据库平台提供了很大的便利,比如Oracle 没有Decimal类型,没有real 类型,要使用非整形的数字类型,只有使用Number类型,那么为SqlServer设计使用的实体类,一般情况下也可以直接在Oracle下使用。
&&& 下面的代码是一个完整的使用实体类的枚举属性的例子:
using System.Collections.G
//using System.L
using System.T
using PWMIS.DataMap.E
namespace OQLTest
public enum RoleNames
public partial class Users : EntityBase
public Users()
TableName = "LT_Users";
EntityMap = EntityMapType.T
//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 _
public UserRoles Roles
if (_roles == null)
_roles = new UserRoles() { ID = this.RoleID };
EntityQuery&UserRoles&.Fill(_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)
.Where(user.NickName, user.RoleID)
.OrderBy(user.ID)
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 & 0)
Users u = userList[0];
Console.WriteLine("User Type is:"+u.RoleID.ToString());
u.RoleID = RoleNames.U
EntityQuery&Users&.Instance.Update(u);
&&& 程序输出:
&&& 数据库结果界面:
--------------分界线----------------------
是国产的开发框架,支持SQL-MAP、ORM和数据控件 三种编程模型,可以一种或者三种混合使用,是开源的开发框架,供广大.net开发朋友在EF,NH之外,提供第三中选择。欢迎加入。
相关链接:5520人阅读
版权宽松(知识共享-署名-相同方式共享)(26)
我有一个MyEnum
enum MyEnum
MyEnum的值不同,软件就做不同的事。
private static void AllCases()
MyEnum me = (MyEnum) new Random().Next(3);
switch (me)
case MyEnum.One:
Console.WriteLine(1);
case MyEnum.Two:
Console.WriteLine(2);
case MyEnum.Three:
Console.WriteLine(3);
}上面这段代码指定了3个case标签,对应MyEnum的3个值,没有default标签。还有另一种写法,就是省略某个case标签,代之以default标签。
private static void CasesAndDefault()
MyEnum me = (MyEnum)new Random().Next(3);
switch (me)
case MyEnum.One:
Console.WriteLine(1);
case MyEnum.Two:
Console.WriteLine(2);
Console.WriteLine(3);
上面这两种写法,那种更好呢?
从扩展性和枚举的意义上考虑,如果该枚举类型可能增加新的成员,则应该使用case语句(,还可以写上default标签,并抛出NotImplementedException,以防枚举增加了新值,case标签忘了加)。
如果是不会增加新成员的枚举,如星期几,那用哪种写法呢?
我这回从IL角度分析,将上面两段代码从IL反编译,得到如下两段代码。
可以发现,两段代码只有switch指令和其后的一个指令不同,写出所有case语句(AllCases)的代码比留一个case,改为default(casesAndDefault)多一点。
所以,当您考虑了写不写default标签的其他情况,仍无法作出决定时,可以参考本文,我建议选择写default,省略一个case。
爱让一切都对了
本文依照知识共享-署名-相同方式3.0共享
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
本博客所有文章,如有版权声明,则往往是;若无,则认为是保留所有版权。以上两种版权,与目前的百度百科、百度文库等版权协议不符,故此禁止张贴。作者享有一切权利追究侵权事宜。
访问:453228次
积分:4576
积分:4576
排名:第4348名
原创:95篇
评论:101条
(1)(2)(2)(1)(1)(1)(2)(1)(1)(3)(2)(5)(1)(1)(3)(4)(4)(3)(7)(2)(1)(3)(3)(5)(1)(1)(1)(1)(4)(1)(1)(1)(5)(8)(4)(1)(2)(2)(3)(1)(1)(1)(1)3651人阅读
Linux(27)
C/C++(60)
&&& 每个枚举都有取值范围,通过强制类型转换,可以将取值范围内的任何整数赋给枚举变量,即使这个值不是枚举值.例如:假设bits和Myflag的定义如下:
enum bits{one = 1,two = 2,four = 4,eight};
则bit = bits(6);是合法的,其中,6不是枚举值,但它是属于枚举值范围内的.
&&& 取值范围定义如下:
&&& 首先,要找到上线,找到枚举量的最大值,找到大于这个最大值的,最小的2的幂,将它减去1,便是取值范围的上限,例如对于:
enum bigstep{first,second = 100,third};最大枚举值是101,在2的幂中,比这个值大的最小的值为128,因此取值范围上限为127.要知道下限,需要知道枚举量的最小值.如果它不小于0,则取值范围的下限为0.否则,采取与寻找上限方式同样的方式,但加上负号,例如,如果最小的枚举量为-6,则比它小的,2的幂最大的值为-8,加1之后为-7.于是,上限与下限便能算出来.
//但是论坛里有人说这个与编译器有关,若把enum的类型作为int的,取值范围为-2,147,483,648 &= X &= 2,147,483,647,若为long型,则更大.
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:83179次
积分:1471
积分:1471
排名:千里之外
原创:47篇
转载:54篇
评论:11条
(1)(3)(7)(7)(1)(1)(1)(2)(1)(7)(3)(3)(1)(7)(10)(1)(1)(5)(3)(1)(5)(1)(3)(2)(2)(4)(4)(5)(3)(5)&&&&&&&&&&&&&
评论- 140&
1、每个枚举成员均具有相关联的常数值。此值的类型就是包含了它的那个枚举的基础类型。每个枚举成员的常数值必须在该枚举的基础类型的范围之内。示例
enum Color: uint
{ Red = -1, Green = -2, Blue = -3 }
产生编译时错误,原因是常数值 -1、-2 和 –3 不在基础整型 uint 的范围内。
2、枚举默认类型是int,从0开始
3、多个枚举成员可以共享同一个关联值。示例
enum Color
{ Red, Green, Blue, Max = Blue }
显示一个枚举,其中的两个枚举成员(Blue 和 Max)具有相同的关联值。
4、一个枚举成员的关联值或隐式地、或显式地被赋值。如果枚举成员的声明中具有“常数表达式”初始值设定项,则该常数表达式的值(它隐式转换为枚举的基础类型)就是该枚举成员的关联值。如果枚举成员的声明不具有初始值设定项,则它的关联值按下面规则隐式地设置:
5、如果枚举成员是在枚举类型中声明的第一个枚举成员,则它的关联值为零。 否则,枚举成员的关联值是通过将前一个枚举成员(按照文本顺序)的关联值加 1 得到的。这样增加后的值必须在该基础类型可表示的值的范围内;否则,会出现编译时错误。
enum Color
{ Red, Green = 10, Blue }
则:Red = 0 &Green = 10 &Blue = 11
原因如下:
枚举成员 Red 被自动赋予零值(因为它不具有初始值设定项并且是第一个枚举成员)。
枚举成员 Green 被显式赋予值 10。
枚举成员 Blue 被自动赋予比文本上位于它前面的成员大 1 的值。
6、枚举成员的关联值不能直接或间接地使用它自己的关联枚举成员的值。除了这个循环性限制外,枚举成员初始值设定项可以自由地引用其他的枚举成员初始值设定项,而不必考虑它们所在的文本位置的排列顺序。在枚举成员初始值设定项内,其他枚举成员的值始终被视为属于所对应的基础类型,因此在引用其他枚举成员时,没有必要使用强制转换。
enum Circular
{ A = B, B }
产生编译时错误,因为 A 和 B 的声明是循环的。A 显式依赖于 B,而 B 隐式依赖于 A。
7、枚举成员的命名方式和作用范围与类中的字段完全类似。枚举成员的范围是包含了它的枚举类型的体。在该范围内,枚举成员可以用它们的简单名称引用。在所有其他代码中,枚举成员的名称必须用它的枚举类型的名称限定。枚举成员不具有任何声明可访问性,如果一个枚举类型是可访问的,则它所含的所有枚举成员都是可访问的。
1、&枚举转常数
(int)Color.Red = 0
(int)Color.Green = 10
2、&常数转枚举
Color mycolor = (Color)0
3、&根据常数取枚举名
Enum.GetName(typeof(Color),0)) = ”Red”
Enum.GetName(typeof(Color),10)) = ”Green”
4、&枚举转字符串
Color.Red.ToString() = ”Red”
5、&字符串转枚举
String str = “Red”
Color mycolor = (Color)Enum.Parse(typeof(Color),str,false)
阅读(...) 评论()可空枚举的处理方法 - 停留的风 - 博客园
posts - 232, comments - 1205, trackbacks - 5, articles - 27
在使用枚举的时候的,经常希望可以对枚举赋值为Null,或者清空枚举值。但是常用的枚举,就是固定的几项。而且不能对值类型赋值为Null。如何来实现可空枚举?
要求保留到数据库中的值,需要为NULL。这种情况在业务开发中经常出现。
尽管问题较小,但是可以探讨下解决方案,找到一种最优解。
方法1:将存储值定义可空类型
/// &summary&
/// 单据状态,记录枚举值
/// &/summary&
public int? State { get; set; }
可行,如果为空,则数据库存储的值也为Null.
缺点:不方便我们对枚举进行展现和赋值,通常直接使用枚举,参见方法2。
方法2:定义枚举字段,并将其定义为可空类型
/// &summary&
/// &/summary&
public RecordState? State { get; set; }
这种方法较上面的方法较好,同样能够实现此功能。
缺点:通常枚举值的展现是展现枚举的所有项,一般使用下拉框,必须选中一项。这样无法实现可空情况。如果要实现所需功能,需要在显示时,做下处理,加入空项。
方法3:在枚举中定义空项,并在写入数据库,或取值时进行的相关的转换
3.1 定义枚举:
/// &summary&
/// 记录状态
/// &/summary&
public enum RecordState
/// &summary&
/// &/summary&
/// &summary&
/// &/summary&
/// &summary&
/// &/summary&
/// &summary&
/// &/summary&
3.2 使用枚举:
/// &summary&
/// &/summary&
public class Doc
/// &summary&
/// &/summary&
public string DocNo { get; set; }
/// &summary&
/// 单据状态
/// &/summary&
public RecordState State { get; set; }
/// &summary&
/// 构造函数
/// &/summary&
public Doc()
下面是数据时需要特别注意的:
写入数据库时,处理情况,参数赋值情况,这样其数据库的值才为NULL,
SqlParameter param = new SqlParameter("State",SqlDbType.SmallInt);
if (doc.State == RecordState.None)
param.Value = DBNull.V
param.Value = doc.S
加载对象时:加载出来又是枚举项
//SqlDataReader reader
Doc doc = new Doc();
if (reader["State"] == DBNull.Value)
doc.State = RecordState.N
doc.State =(RecordState)reader.GetInt16(reader.GetOrdinal("State"));

我要回帖

更多关于 判断枚举是否为空 的文章

 

随机推荐