locked
Problem with lambda expression containing equality operator for byte values

    问题

  • Hi!

    I am building an application with NHibernate with the latest source from the trunk which now includes a new Linq provider. When I encountered the problem I thought it might be the expression visitors for NHibernate. However later I realized that the problem was due to the lambda expression.

    Given the lambda expression below where Province type contains a public property "byte CountryId" and Country type which contains a public property "byte Id". The expression later evaluates to a NHibernate query where the Province table is queried for CountryId values equal to local variable country.Id which is a constant expression.

    The exception message was related to the DbCommand generated by the expression visitors of NHibernate, which stated that the parameter type for
    CountryId field is byte and cannot be set to a value of type Int32.


    Expression<Func<Province, bool>> exp = p => p.CountryId == country.Id;
    
    

    When I inspected the expression variable exp, I found out that both sides of the equality operator were converted to Int32.

    {p => (Convert(p.CountryId) = Convert(value(AddressToGo.Business.Default.AddressComponents+<>c__DisplayClass0).country.Id))}
    
    

    I can't understand why the equality operator for two byte values need those values to be converted to Int32 beforehand. I need a proper way to override this behavior. Using Equals() method call (which indeed leads to MethodCallExpression where the byte values are not converted to Int32) is not option since NHibernate Linq provider doesn't support Equals() MethodCallExpression.

    I suppose preparing the expression with static methods provided by the Expression class might be a solution however I still wonder about the reason behind this conversion.

    Thanks in advance.

    Edit: Building the lambda expression with static methods provided by Expression class works perfectly without conversion expressions;

    Expression<Func<Province, bool>> exp = 
              Expression.Lambda<Func<Province, bool>>
              (
                Expression.Equal
                (
                  Expression.MakeMemberAccess(Expression.Parameter(typeof(Province), "p"), typeof(Province).GetProperty("CountryId")),
                  Expression.Constant(country.Id, typeof(byte))
                ),
                Expression.Parameter(typeof(Province), "p")
              );

    • 已编辑 odul 2010年1月11日 20:07 Added working expression
    2010年1月11日 19:20

答案

  • Hi,

    I think this is due to the compiler by default will convert byte to int to do the comparation when it's analysing lambda expression, in your second code example you actually didn't use lambda expression, therefore compiler doesn't need to do the analysing therefore the convert will not happan.

    Thanks
    Binze
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    2010年1月14日 9:59