Skip to content
This repository has been archived by the owner on Aug 2, 2019. It is now read-only.

Issue with Any in OData $filter clause. #23

Closed
adamfairstr opened this issue Jul 31, 2015 · 2 comments
Closed

Issue with Any in OData $filter clause. #23

adamfairstr opened this issue Jul 31, 2015 · 2 comments

Comments

@adamfairstr
Copy link

Hi,

Thanks for this great library. I'd love to see it grow.

I've got an issue with a queries such as:

people?$filter=EmploymentsList/any(o: o/Salary eq 2.5)

Where EmploymentsList is a property on People and is defined as:

   private readonly ISet<Employment> employmentsList= new HashSet<Employment>();

   public virtual IEnumerable<Employment> EmploymentsList 
   {
      get { return this.employmentsList; }
   }

I receive the following error:

"Cannot get collection item type"

Unfortunately, I cannot change the definition of .EmploymentsList and so would like to change nHibernate.odata instead. I can see the issue lies in NHibernate.OData.TypeUtil.TryGetCollectionItemType at this line:

   System.Type enumerableType = collectionType.GetInterfaces().FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>));

And enumerableType is returned as null.

Unfortunately, my knowledge of reflection isn't brilliant and would need some pointers but would adding a line such as:

   if (enumerableType == null) enumerableType = collectionType;

be acceptable? If it is, I'll get on and write a unit test and send a pull request.

@adamfairstr adamfairstr changed the title Issue with Issue with Any in OData $filter clause. Jul 31, 2015
@dsigitov
Copy link
Contributor

Hi!

but would adding a line such as:
if (enumerableType == null) enumerableType = collectionType;
be acceptable? If it is, I'll get on and write a unit test and send a pull request.

I wouldn't recommend doing that. It will totally break the logic of this method.

The problem is that method doesn't handle correctly the case when collectionType is IEnumerable<T> itself.

Instead, change the method as follows:

public static System.Type TryGetCollectionItemType(System.Type collectionType)
{
    if (collectionType == null)
        return null;

    System.Type enumerableType;
    if (collectionType.IsGenericType && collectionType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        enumerableType = collectionType;
    else
        enumerableType = collectionType.GetInterfaces().FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IEnumerable<>));

    if (enumerableType == null)
        return null;

    return enumerableType.GetGenericArguments().Single();
}

It will first check whether the value of collectionType is IEnumerable<T> itself, then it will check all interfaces, so this test will pass:

Assert.AreEqual(typeof(int), OData.TypeUtil.TryGetCollectionItemType(typeof(IEnumerable<int>)));

pvginkel added a commit that referenced this issue Sep 27, 2015
The code that recognizes whether a property is a collection did not check the actual type of the collection for being an enumerable interface.

Bug: #23
@pvginkel
Copy link
Owner

Sorry for the late reply. I'll push a new version to NuGet in a moment with this fix.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants