ArgumentNullException is there is a literal null in a projection

Posts   
 
    
TomDog
User
Posts: 623
Joined: 25-Oct-2005
# Posted on: 03-Feb-2011 23:11:09   

If I have a query against like this against northwind

select new {c.Address, c.City, CompanyName = (string)null, c.ContactName, c.ContactTitle, c.Country, c.CustomerId, c.Fax, c.Phone, c.PostalCode, c.Region}

It will fail with a ArgumentNullException which on the face of it is fair enough, but if instead of the anonymous you where projecting into a constructor e.g

var queryable = from c in GetNorthwindLinqMetaData().Customer                
select new CustomerVM(c.Address, c.City, null, c.ContactName, c.ContactTitle, c.Country, c.CustomerId, c.Fax, c.Phone, c.PostalCode, c.Region);
queryable.ToList();

It will also fail, which means you can't pass a literal null to constructor which doesn't seem so fair. Thoughts?

One of our developers ran into this when he tried to reuse a constructor by passing nulls rather than creating a new one, his knee jerk reaction to this (and any other linq to DB) problem was too ToList() before the projection and prefetch frowning cry

To repro see http://rapiddevbookcode.codeplex.com/SourceControl/changeset/view/84374#1647590

Jeremy Thomas
Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 04-Feb-2011 07:58:20   

Which runtime library version (build number) are you using? (ORMSupportClasses & LinqSupportClasses).

TomDog
User
Posts: 623
Joined: 25-Oct-2005
# Posted on: 04-Feb-2011 08:45:38   

Walaa wrote:

Which runtime library version (build number) are you using? (ORMSupportClasses & LinqSupportClasses).

both 3.0.11.125

Jeremy Thomas
Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 04-Feb-2011 08:55:49   

Try this:

                var queryable = from c in  GetNorthwindLinqMetaData().Customer
                                select new CustomerVM(c.Address, c.City, DBNull.Value.ToString(), c.ContactName, c.ContactTitle, c.Country, c.CustomerId, c.Fax, c.Phone, c.PostalCode, c.Region);
                queryable.ToList();
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 04-Feb-2011 09:43:10   

Will see where it dies, should work (as the null is a constant and is going to the DB and back anyway like any other constant it seems.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 04-Feb-2011 11:19:52   

The element to add to the projection is 'null' and there's no logic in place to deal with that, however it should simply ignore it if it is null (so it will become null in the first place), in the anonymous type variant. Will see if that makes a difference.

The CTor variant... I don't know if that's possible to do, I'll check.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 04-Feb-2011 11:30:15   

Changed it internally from null to DBNull.Value (as that would make everything work perfectly, as the value is sent to the DB and comes back as DBNull.Value anyway, and is handled properly with the projectors, similar to a normal null value):


[Test]
public void NullInProjectionAsConstant()
{
    using(DataAccessAdapter adapter = new DataAccessAdapter())
    {
        LinqMetaData metaData = new LinqMetaData(adapter);
        var q = from c in metaData.Customer
                select new { c.CustomerId, Foo = (string)null, c.CompanyName };

        foreach(var v in q)
        {
            Assert.IsNull(v.Foo);
        }
    }
}

Now looking into the ctor stuff, should now also work. I must say you do seem to run into a lot of edge cases. Anyway, we're working on a fluent interface, SQL like, for our own api as well (which should work with 2.6 and up), to provide a valid alternative when things fall apart in edge cases in linq queries. Often these edge cases are a nightmare to debug, left alone fix, while the current api of our query system is pretty low level, so it's not always a valuable alternative.

they now also work:


[Test]
public void NullInProjectionAsConstant2()
{
    using(DataAccessAdapter adapter = new DataAccessAdapter())
    {
        LinqMetaData metaData = new LinqMetaData(adapter);
        var q = from c in metaData.Customer
                select new Customer() {CustId = c.CustomerId, Contact = null, CompanyNme = c.CompanyName };

        foreach(var v in q)
        {
            Assert.IsNull(v.Contact);
        }
    }
}

[Test]
public void NullInProjectionAsConstant3()
{
    using(DataAccessAdapter adapter = new DataAccessAdapter())
    {
        LinqMetaData metaData = new LinqMetaData(adapter);
        var q = from c in metaData.Customer
                select new Customer(c.CustomerId, null, c.CompanyName);

        foreach(var v in q)
        {
            Assert.IsNull(v.Contact);
        }
    }
}

will attach a new build.

(edit) attached. simple_smile

Frans Bouma | Lead developer LLBLGen Pro
TomDog
User
Posts: 623
Joined: 25-Oct-2005
# Posted on: 06-Feb-2011 22:04:26   

Otis wrote:

I must say you do seem to run into a lot of edge cases.

Just clumsy I guess - though wasn't me personally this time.

Otis wrote:

Anyway, we're working on a fluent interface, SQL like, for our own api as well (which should work with 2.6 and up), to provide a valid alternative when things fall apart in edge cases in linq queries.

Interesting sunglasses

Jeremy Thomas
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 07-Feb-2011 09:00:30   

TomDog wrote:

Otis wrote:

I must say you do seem to run into a lot of edge cases.

Just clumsy I guess - though wasn't me personally this time.

Oh it wasn't criticism, I think it's caused by your more complex than average model. simple_smile

Otis wrote:

Anyway, we're working on a fluent interface, SQL like, for our own api as well (which should work with 2.6 and up), to provide a valid alternative when things fall apart in edge cases in linq queries.

Interesting sunglasses

Things look good so far, we don't have a beta date in sight at the moment though. We plan to release a first beta of it after we've rewritten all linq tests into this api to see whether it can do everything we want. simple_smile

Frans Bouma | Lead developer LLBLGen Pro