Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NRE with nullable subselect value in Linq #2425

Closed
NikitaEgorov opened this issue Jul 4, 2020 · 5 comments · Fixed by #2428
Closed

NRE with nullable subselect value in Linq #2425

NikitaEgorov opened this issue Jul 4, 2020 · 5 comments · Fixed by #2428

Comments

@NikitaEgorov
Copy link

Version: NHibernate-5.3.0
Exception:
Object reference not set to an instance of an object.

   at System.Linq.Enumerable.SelectEnumerableIterator`2.ToList()
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at NHibernate.Linq.ResultTransformer.TransformList(IList collection) in r:\nhibernate-core-master\src\NHibernate\Linq\ResultTransformer.cs:line 36

LINQ Expression:

.Select(
    x => new
        {
            x.Date,
            x.Employee.Number,
            CountyNumber = (int?)x.Site.CountyNumber, <=== Pass through null value
            Item = x.Items.Select(zx => new { zx.Value }) <=== Subselect
        })

listTransformers[1].ToString()

inputList => inputList
    .Select(g => new <>f__AnonymousType1`4(
                Date = Convert(g.Key.Items[1], Nullable`1), 
                Number = Convert(g.Key.Items[2], Int32), 
                CountyNumber = Convert(Convert(g.Key.Items[3], Int32), Nullable`1), <======== Int32 shoud be Nullable
                Item = Convert(g.Where(t => Not(ReferenceEquals(t.Items[0], null))).Select(value => new <>f__AnonymousType2`1(BaseValue = Convert(value.Items[1], Nullable`1))).ToList().AsReadOnly(), IEnumerable`1))).ToList()

Exception happened only if Select contains "Subselect" and any value "pass" through null value

@maca88
Copy link
Contributor

maca88 commented Jul 6, 2020

This issue should be fixed by #2079, where a friendlier exception is thrown when the cast is missing:

var exception = Assert.Throws<GenericADOException>(() =>
{
db.Animals.Select(
a => new
{
BodyWeight = (string.IsNullOrWhiteSpace(a.Description)
? a.Mother.Mother.BodyWeight
: a.Father.Mother.BodyWeight)
})
.ToList();
});
Assert.That(exception.InnerException, Is.TypeOf<InvalidOperationException>());
Assert.That(exception.InnerException.Message, Is.EqualTo(
"Null value cannot be assigned to a value type 'System.Double'. " +
"Cast expression 'IIF(IsNullOrWhiteSpace([a].Description), [_3].BodyWeight, [_1].BodyWeight)' to 'System.Nullable`1[System.Double]'."));
var list = db.Animals.Select(
a => new
{
BodyWeight = (double?) (string.IsNullOrWhiteSpace(a.Description)
? a.Mother.Mother.BodyWeight
: a.Father.Mother.BodyWeight)
})
.ToList();
Assert.That(list, Has.Exactly(0).With.Property("BodyWeight").Not.Null);

In order to assure that the issue is fixed by the mentioned PR, it would be nice if you provide the whole linq query so that it can be added to the tests.

@NikitaEgorov
Copy link
Author

I reproduced this issue on master branch nhibernate

@maca88
Copy link
Contributor

maca88 commented Jul 6, 2020

The mentioned PR is not yet merged into master, you need to build the code from the PR in order to test it.

@NikitaEgorov
Copy link
Author

NikitaEgorov commented Jul 7, 2020

[Test]
public void CanExecuteMethodWithNullObjectAndSubselect()
{
    var list1 = db.Animals.Select(
                                    a => new
                                        {
                                            NullableId = (int?) a.Father.Father.Id,
                                        })
                    .ToList();
    Assert.That(list1, Has.Count.GreaterThan(0));
    Assert.That(list1[0].NullableId, Is.Null);

    var list2 = db.Animals.Select(
                                    a => new
                                        {
                                            Descriptions = a.Children.Select(z => z.Description)
                                        })
                    .ToList();
    Assert.That(list2, Has.Count.GreaterThan(0));
    Assert.That(list2[0].Descriptions, Is.Not.Null);

    var list3 = db.Animals.Select(
                                a => new
                                        {
                                            NullableId = (int?) a.Father.Father.Id,
                                            Descriptions = a.Children.Select(z=>z.Description)
                                        })
                .ToList();
    Assert.That(list3, Has.Count.GreaterThan(0));
    Assert.That(list3[0].NullableId, Is.Null);
    Assert.That(list3[0].Descriptions, Is.Not.Null);
}
NHibernate.Exceptions.GenericADOException : Could not execute query[SQL: SQL not available]
  ----> System.NullReferenceException : Object reference not set to an instance of an object.
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results, Object filterConnection) in r:\nhibernate-core-GH2054\src\NHibernate\Impl\SessionImpl.cs:line 560
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) in r:\nhibernate-core-GH2054\src\NHibernate\Impl\SessionImpl.cs:line 520
   at NHibernate.Impl.AbstractSessionImpl.List[T](IQueryExpression query, QueryParameters parameters) in r:\nhibernate-core-GH2054\src\NHibernate\Impl\AbstractSessionImpl.cs:line 150
   at NHibernate.Impl.AbstractQueryImpl2.List[T]() in r:\nhibernate-core-GH2054\src\NHibernate\Impl\AbstractQueryImpl2.cs:line 111
   at NHibernate.Linq.DefaultQueryProvider.ExecuteList[TResult](Expression expression) in r:\nhibernate-core-GH2054\src\NHibernate\Linq\DefaultQueryProvider.cs:line 111
   at NHibernate.Linq.NhQueryable`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() in r:\nhibernate-core-GH2054\src\NHibernate\Linq\NhQueryable.cs:line 65
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at NHibernate.Test.Linq.SelectionTests.CanExecuteMethodWithNullObjectAndSubselect() in r:\nhibernate-core-GH2054\src\NHibernate.Test\Linq\SelectionTests.cs:line 1167
--NullReferenceException
   at lambda_method(Closure , IGrouping`2 )
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at NHibernate.Linq.ResultTransformer.TransformList(IList collection) in r:\nhibernate-core-GH2054\src\NHibernate\Linq\ResultTransformer.cs:line 36
   at NHibernate.Loader.Hql.QueryLoader.GetResultList(IList results, IResultTransformer resultTransformer) in r:\nhibernate-core-GH2054\src\NHibernate\Loader\Hql\QueryLoader.cs:line 343
   at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) in r:\nhibernate-core-GH2054\src\NHibernate\Loader\Loader.cs:line 1837
   at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces) in r:\nhibernate-core-GH2054\src\NHibernate\Loader\Loader.cs:line 1827
   at NHibernate.Loader.Hql.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters) in r:\nhibernate-core-GH2054\src\NHibernate\Loader\Hql\QueryLoader.cs:line 325
   at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters) in r:\nhibernate-core-GH2054\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs:line 131
   at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results) in r:\nhibernate-core-GH2054\src\NHibernate\Engine\Query\HQLQueryPlan.cs:line 115
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results, Object filterConnection) in r:\nhibernate-core-GH2054\src\NHibernate\Impl\SessionImpl.cs:line 550

@maca88
Copy link
Contributor

maca88 commented Jul 7, 2020

Thanks for providing the test case, I made a fix in #2428.

@fredericDelaporte fredericDelaporte changed the title System.NullReferenceException: 'Object reference not set to an instance of an object.' NRE with nullable subselect value in Linq Jul 11, 2020
@fredericDelaporte fredericDelaporte added this to the 5.3 milestone Jul 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants