博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Entity Framework 5.0运行.NET Framework 4.0之上在查询表达式中使用显示转换的一个问题...
阅读量:5863 次
发布时间:2019-06-19

本文共 3781 字,大约阅读时间需要 12 分钟。

EF使用版本File Version:4.4.20627.0、Product Version:5.0.0.net40,今天在其中一个测试环境(Windows Server 2008 R2、.NET Framework 4.0)发现执行一个查询会抛出如下异常信息(由于寄宿体的原因这个异常通过sos的!StopOnException命令还无法直接捕捉):

System.ArgumentException: The specified value is not an instance of type 'Edm.Int32' Parameter name: value at System.Data.Common.CommandTrees.ExpressionBuilder.Internal.ArgumentValidation.ValidateConstant(TypeUsage constantType, Object value) at System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.MemberAccessTranslator.TypedTranslate(ExpressionConverter parent, MemberExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.UnaryTranslator.TypedTranslate(ExpressionConverter parent, UnaryExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Objects.ELinq.ExpressionConverter.EqualsTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.BitwiseBinaryTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpre...

经过排查缩减导致这个错误的原因是一个Int32赋值生成的查询表达式所致,简略实体定义参考如下:

/// /// 消息处理状态/// public enum HandleStatus{    ///     /// 成功    ///     /// 
0
Success = 0, /// /// 失败 /// ///
1
Failed,}/// /// 消息处理队列查询条件/// public sealed class HandleQueueCondition{ /// /// 发送队列状态 /// public Nullable
Status { get; set; }}///
/// 消息处理队列项/// [Table("Core_Messaging_HandleQueue"), Serializable]public sealed class HandleQueueItem{ ///
/// 发送状态 /// [NotMapped] public HandleStatus Status { get { return (HandleStatus)this.StatusValue; } set { this.StatusValue = (Int32)value; } } ///
/// 发送状态值 /// ///
用户EF的实体映射
[Column("Status")] public Int32 StatusValue { get; set; }}

为了解决EF 5.0不支持枚举值的现状,我们通过一个中间值保存返回它。生成表达式的部分代码如下:

/// /// 查询列表/// /// 数据库上下文/// 查询条件/// 
查询列表
private IEnumerable
QueryList(MessagingDbContext dbContext, HandleQueueCondition condition){ Expression
> predicate = PredicateExtension.True
(); if (condition.Status.HasValue) predicate = predicate.And
(p => p.StatusValue == (Int32)condition.Status.Value); return dbContext.HandleQueueItems.Where(predicate) .OrderByDescending(p => p.DateCreated) .Skip(condition.PageIndex * condition.PageSize) .Take(condition.PageSize) .ToList();}

PredicateExtension是针对Expression<Func<T, Boolean>>的扩展,用于合并多个条件表达式。用WinDbg + sos调试,设置断点在System.Data.Entity.dll的System.Data.Common.CommandTrees.ExpressionBuilder.Internal.ArgumentValidation.ValidateConstant函数上发现constantType的名称是Edm.Int32、而value并不是转换后的Int32值而是枚举类型HandleStatus。相同的代码在安装.NET Framework 4.5的测试环境没有问题,通过升级到4.5版本可以解决这个缺陷。

4.0和4.5对于包含转换层级的函数解析表达式都会失败(比如:Convert.Toxxx),但是对于一个显示转换则不同,看更简单的代码段:

dbContext.HandleQueueItems.Where(p => p.StatusValue == Convert.ToInt32(condition.Status.Value))    .OrderByDescending(p => p.DateCreated)    .Skip(condition.PageIndex * condition.PageSize)    .Take(condition.PageSize)    .ToList();

显示转换下两个版本输出的表达式相同((p.StatusValue == Convert(value(ConsoleApplication1.Program+<>c__DisplayClass0).condition.Status.Value))):

dbContext.HandleQueueItems.Where(p => p.StatusValue == ((Int32)condition.Status.Value))    .OrderByDescending(p => p.DateCreated)    .Skip(condition.PageIndex * condition.PageSize)    .Take(condition.PageSize)    .ToList();

真正的变化在于System.Data.Entity的System.Data.Objects.ELinq.ExpressionConverter内部。

转载地址:http://axunx.baihongyu.com/

你可能感兴趣的文章
Mahout介绍和简单应用
查看>>
ping命令
查看>>
关于z-index 属性和层级覆盖的相关学习
查看>>
安装MySQLdb时出错:EnvironmentError: mysql_config not found
查看>>
Linux df
查看>>
Python——getpass
查看>>
理解 Redis(5) - 哈希值
查看>>
【Node.js】Stream(流)的学习笔记
查看>>
Django 过滤器 、日期格式化、数学运算
查看>>
【总结整理】关于写前端页面小技巧
查看>>
java===java基础学习(6)---流程控制,for,if,switch,continue,break
查看>>
使用Node搭建reactSSR服务端渲染架构
查看>>
Android下VideoView的研究
查看>>
Maven中settings.xml的配置项说明
查看>>
文件缓存
查看>>
时间管理之“二”定律
查看>>
NYOJ71:独木舟上的旅行(简单贪心)
查看>>
新公司注册流程
查看>>
POJ - 1251 Jungle Roads(最小生成树)
查看>>
Fixflow引擎解析(五)(内核) - 基于Token驱动的引擎内核运转原理
查看>>