views:

50

answers:

2

I have the following statement that's throwing an error I don't understand:

return (int) _session.CreateCriteria<T>()
    .Add(LambdaSubquery.Property<Fund>(x => x.Id)
        .In(GetAvailableIdsPerDataUniverse(x => x.GetDataUniverseId())))
    .AddNameSearchCriteria<T>(searchExpression)
    .SetProjection(LambdaProjection.Count<T>(e => e.Id))
    .UniqueResult();

This is the error:

Unrecognised method call in epression x.GetDataUniverseId()

Background:

I have some different types that I need to perform searches for. Each of these types implement ISearchable which requires that they have Name & Id properties as well as the GetDataUniverseId() method, which will return an expression representing the dataUniverseId needed for the LambdaProjection.

The method GetAvailableIdsPerDataUniverse(x => x.GetDataUniverseId()) has the following signature:

protected DetachedCriteria 
GetAvailableIdsPerDataUniverse(System.Linq.Expressions.Expression<Func<Fund, object>> dataUniverseId)

and x => x.GetDataUniverseId() is defined in my Fund class as

public virtual System.Linq.Expressions.Expression<Func<Fund, object>> GetDataUniverseId()
{
    return f => f.Id;
}

and for example as the following in the Company class:

public virtual Expression<Func<Fund, object>> GetDataUniverseId()
{
    return f => f.Company.Id;
}

This works if instead if instead of trying to pass x => x.GetDataUniverseId() as the parameter, I 'hard-code' f => f.Id or f => f.Company.Id. I'd like it if the type being worked on was able to supply the expression it needed rather than me having to pass that expression into every method that uses GetAvailableIdsPerDataUniverse(). I thought that instead of accessing a property on the inferred type, it could execute a method that would return the expression.

Question:

Is there anything I can do to resolve this error?

Note:

Everything builds fine, so I was a little surprised to see that it threw an error when I ran it. Mostly because when I passed in the expression as a paramater that I 'hard-coded' it worked fine.

Also, I've also tried the following to no avail, where I specify the type I want GetAvailableIdsPerDataUniverse to act on:

.In(GetAvailableIdsPerDataUniverse<Fund>(x => x.GetDataUniverseId())))
A: 

Try:

return (int) _session.CreateCriteria<T>()
    .Add(LambdaSubquery.Property<Fund>(x => x.Id)
        .In(GetAvailableIdsPerDataUniverse(y => y.GetDataUniverseId())))
    .AddNameSearchCriteria<T>(searchExpression)
    .SetProjection(LambdaProjection.Count<T>(e => e.Id))
    .UniqueResult();
Sunny
Please delete this. It's not an answer. It's a joke
DaveDev
A: 

I've been informed that the problem here is that I want the behaviour of polymorphic static methods, but I can't have that because GetDataUniverseId is not an instance method, and I need an instance to be able to use it polymorphically.

The solution, although inefficient because it uses lots of reflection is to use new T()

such that

    .Add(LambdaSubquery.Property<Fund>(x => x.Id)
        .In(GetAvailableIdsPerDataUniverse(x => x.GetDataUniverseId())))

becomes

    .Add(LambdaSubquery.Property<Fund>(x => x.Id)
        .In(GetAvailableIdsPerDataUniverse((new T()).GetDataUniverseId())))

The only other issue with this is that the method this exists inside:

    public IEnumerable<T> GetEntitiesByName<T>(int pageSize, string searchExpression)
        where T : class, ISearchableEntity

must now have the new() constraint, as follows:

    public IEnumerable<T> GetEntitiesByName<T>(int pageSize, string searchExpression) 
        where T : class, ISearchableEntity, new()

I hope somebody finds more use from this than the 'answer' provided by @Sunny

DaveDev
Sunny
If that's the case, fair enough. But I'm sure you can understand my frustration. If that was your genuine intent you should update your answer with an explanation. We can then work on squaring the record.
DaveDev