我刚刚遇到NHibernate中的一个错误,该错误恰好已经被提出:https: //nhibernate.jira.com/browse/NH-2763
我不确定这是否适用于枚举以外的任何其他内容,但是当使用VB中的Lambda时,它看起来与C#中的相同Lambda不同.
C#:
Where(x => x.Status == EmployeeStatus.Active)
Run Code Online (Sandbox Code Playgroud)
VB
Where(Function(x) x.Status = EmployeeStatus.Active)
Run Code Online (Sandbox Code Playgroud)
就我所知,它们是一样的吗?(我的VB不是很好)
如果我在同一行代码上放置一个断点,那么上面的代码将被传入.在C#我得到:

在VB版本传入的同一行,我得到:

这是我做错了吗?结果是否相同,只是在C#/ VB之间显示不同?
编辑: 好的,所以它们显示不同,但它们不能相同,因为NHibernate无法处理它.NHibernate完全处理了C#版本,VB版本在抛出以下异常时解析:

NHibernate StackTrace:
at NHibernate.Impl.ExpressionProcessor.FindMemberExpression(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 168
at NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression(Expression left, Expression right, ExpressionType nodeType) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 323
at NHibernate.Impl.ExpressionProcessor.ProcessSimpleExpression(BinaryExpression be) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 316
at NHibernate.Impl.ExpressionProcessor.ProcessBinaryExpression(BinaryExpression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 418
at NHibernate.Impl.ExpressionProcessor.ProcessExpression(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 486
at NHibernate.Impl.ExpressionProcessor.ProcessExpression[T](Expression`1 expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\ExpressionProcessor.cs:line 504
at NHibernate.Criterion.QueryOver`2.Add(Expression`1 expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Criterion\QueryOver.cs:line 635
at NHibernate.Criterion.QueryOver`2.NHibernate.IQueryOver<TRoot,TSubType>.Where(Expression`1 expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Criterion\QueryOver.cs:line 686
at *removed*.EmployeeRepository.GetByEntityId(Int64 entityId, Expression`1 basicCriteria) in D:\*removed*\EmployeeRepository.cs:line 76
Run Code Online (Sandbox Code Playgroud)
那两者之间一定有什么不同?
编辑2:
对于乔纳森.这是使用表达式的方法:
public IEnumerable<Employee> GetByEntityId(long entityId, Expression<Func<Employee, bool>> basicCriteria)
{
IEnumerable<Employee> result;
using (var tx = Session.BeginTransaction())
{
var employeeQuery = Session.QueryOver<Employee>()
.Where(x => x.EntityId == entityId);
if (basicCriteria != null)
employeeQuery = employeeQuery.Where(basicCriteria);
result = employeeQuery.List();
tx.Commit();
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
Gab*_*abe 10
你所看到的差异与lambdas无关; 它只是语言语义的差异.VB正在向函数发出调用,如果整数溢出(因此Checked是名称的一部分),默认情况下抛出异常.
默认情况下,C#编译器不会发出"已检查"版本的函数,显然NHibernate是由C#用户开发的,因此它似乎无法识别"已检查"函数.
如果转到项目的"编译"选项并单击"高级编译选项",则可以选中"删除整数溢出检查"框,以便VB具有默认的C#行为,并且不应再出现该错误:

该部分<>__DisplayClass意味着编译器创建了一个闭包.这意味着调试器中的表达式不是您展示的表达式,而是类似的表达式
var status = EmployeeStatus.Active;
Expression<Func<Employee, bool>> expr = x => x.Status == status;
Run Code Online (Sandbox Code Playgroud)
但这不是NHibernate遇到问题的部分.Convert和之间的区别ConvertChecked是.这是由C#和VB.NET之间的语义差异引起的:
在C#中,默认情况下,所有运行时计算都是未选中的,也就是说,不会检查算术溢出.您可以使用更改特定代码段的默认值checked.
在VB中,默认是检查计算,这会导致生成不同的lambda.我相信在VB中也有办法改变这个.
因此,以下C#代码创建与VB相同的lambda:
checked
{
Expression<Func<Employee, bool>> expr = x => x.Status == EmployeeStatus.Active;
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果你没有找到另一个选项,作为最后的手段,你可以使用Convert而不是代码重写VB.NET生成的表达式ConvertChecked:
Class UncheckedVisitor
Inherits ExpressionVisitor
Protected Overrides Function VisitUnary ( _
node As UnaryExpression _
) As Expression
If node.NodeType = ExpressionType.ConvertChecked
node = Expression.Convert(node.Operand, node.Type, node.Method)
End If
Return MyBase.VisitUnary(node)
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
unchechedVisitor.Visit(expr)然后返回expr所有ConvertChecked替换为的实例Convert.
| 归档时间: |
|
| 查看次数: |
1025 次 |
| 最近记录: |