Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq equality comparing not working

Tags:

c#

nhibernate

Given this method:

internal static IEnumerable<Entity> GetByParentImpl<Entity, TKey>(this ICanGetByParent<Entity, TKey> self, TKey parentId, string fieldName) 
    where Entity : class 
{
    RepositoryBase<Entity> rb = (RepositoryBase<Entity>)self;
    rb.unitOfWork.Begin();

    var entities = rb.unitOfWork.Session.QueryOver<Entity>()
        .Where(e => EqualityComparer<TKey>.Default.Equals(GetId<Entity, TKey>(e, fieldName), parentId))
        .List();

    return entities;
}

And this helper:

private static TKey GetId<Entity, TKey>(object obj, string fieldName) where Entity : class
{
    TKey id = default(TKey);

    switch(id.GetType().Name) {
        case "Int32":
            break;
        case "Guid":
            id = (TKey)TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString((string)typeof(Entity).GetField(fieldName).GetValue(obj));
            break;
    }

    return id;
}

I'm getting this exception on my linq statement:

Unrecognised method call: System.Collections.Generic.EqualityComparer`1[[System.Guid, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]:Boolean Equals(System.Guid, System.Guid)

What does this mean? I'm not even sure how to debug this correctly. I could have sworn that the code above was working...

like image 946
Tyler Wright Avatar asked Aug 09 '12 15:08

Tyler Wright


2 Answers

You cannot do comparison in such way for linq to any database provider. Provider cannot transform this into expression tree. So you must use it after .ToArray() or give an Expression<Func<RegisterCardBase, bool>> into Where instead of lambda.

PS: Why are you doing so strange actions with Guid? How it is storaged in database?

like image 197
Kirill Bestemyanov Avatar answered Oct 11 '22 17:10

Kirill Bestemyanov


NHibernate's Linq provider tries to convert the Linq query to HQL and eventually to SQL. The lambda expression you have in your Where method is not supported by default in NHibernate.

However, the NHibernate Linq provider is extensible. You can create your own extensions for handling various unsupported expressions.

Alessandro Giorgetti has a good sample on how to extend Linq provider to support String.Equals with StringComparison option.

Edit

I just realized that you are using QueryOver, and not NHibernate Linq. You should probably remove linq tag. My answer is somewhat relevant if you switch to session.Query<Entity>(). Still, you might reconsider your approach for converting Id and using it in Where.

like image 45
Miroslav Popovic Avatar answered Oct 11 '22 17:10

Miroslav Popovic