Lost contains() filter

Posts   
 
    
joef
User
Posts: 8
Joined: 18-Mar-2016
# Posted on: 07-Nov-2016 11:32:00   

Using version 4.1.14.1023 of the run time dlls with SQL server and dot net 4.0 in Adapter mode.

I have a table called Assets with a nullable integer field called CustodianId. The following code

Dim myOptions As New List(Of Integer)
myOptions.Add(1)
Dim q = From a In metaData.Assets Where (myOptions.Contains(a.CustodianId.GetValueOrDefault) OrElse a.CustodianId Is Nothing)
      Select a.AssetId, a.CustodianId

produces this SQL query

SELECT [LPLA_1].[AssetID] AS [AssetId], [LPLA_1].[CustodianID] AS [CustodianId] FROM [dbo].[Assets]  [LPLA_1]   WHERE ( ( ( ( ( ( [LPLA_1].[CustodianID] IS NULL))))))

I know we should use .Value rather than .GetValueOrDefault but I am still worried that this produces an incorrect query with no compile time or run time error.

Is this still an issue in versions 4.2 or 5?

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 07-Nov-2016 17:05:54   

Reproduced.

using v.5.0.7, with VB and C#.

The also is the smallest reproducible code.

var shipviaList = new List<int>();
shipviaList.Add(1);
shipviaList.Add(2);

using (var db = new DataAccessAdapter())
{
    var linq = new LinqMetaData(db);

    var q = from o in linq.Order
            where shipviaList.Contains(o.ShipVia.GetValueOrDefault())
            select o.OrderId;

    var result = q.ToList();
}

Produces:

SELECT [LPLA_1].[OrderID] AS [OrderId] FROM [NORTHWND].[dbo].[Orders]  [LPLA_1] 

We will look into it.

GetValueOrDefault() runs in memory and is not evaluated at the DB side. If you remove it and use a nullable List, the correct predicate will be generated.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 07-Nov-2016 20:40:49   

Walaa is correct, the in-memory method isn't converted. You don't have to specify .Value btw, the runtime is clever enough to deal with the value itself.

Frans Bouma | Lead developer LLBLGen Pro
joef
User
Posts: 8
Joined: 18-Mar-2016
# Posted on: 08-Nov-2016 11:10:23   

Thank you for your prompt response. Is there any option or configuration we could set to produce a compile or run-time exception in this or similar cases rather than a silent failure?

BTW with option strict on we do have to use either a list of nullable or .Value and in your documentation you recommend using .Value in VB dot net code for filter expressions.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 09-Nov-2016 10:24:48   

We're currently looking into why this doesn't give an exception as further analysis showed it should: if an in-memory method call is used on an element which is used inside the DB (and a field in a where clause is) then the in-memory method has to be converted to a DB construct. If this fails (and for GetValueOrDefault it should, as there's no mapping) an exception should be thrown.

Compiling the query on VB.NET shows the compiler doesn't compile it away, so we think the checker which traverses the tree and marks lambdas which solely work on in-memory expressions makes a mistake here. Using '.Value' instead of GetValueOrDefault makes it work properly, so there's something odd going on.

Looking into it.

Also, noted on the VB.NET and .Value remark, my head was in C# mode. flushed

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 09-Nov-2016 10:48:37   

Found it. It's a bug in the runtime. The .Contains() call is converted to an in-clause expression, and the argument passed to Contains() is a method call (GetValueOrDefault()) which isn't expected, however it's silently ignored.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 09-Nov-2016 11:39:10   

Fixed in 5.0.8 hotfix, now available.

Frans Bouma | Lead developer LLBLGen Pro
joef
User
Posts: 8
Joined: 18-Mar-2016
# Posted on: 10-Nov-2016 14:24:11   

Thank you

joef
User
Posts: 8
Joined: 18-Mar-2016
# Posted on: 21-Nov-2016 12:01:57   

Will this fix be applied to other builds such as 4.1?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39613
Joined: 17-Aug-2003
# Posted on: 21-Nov-2016 14:04:57   

No, this won't be backported to v4.1. It's also not backported to v4.2 as it's not a major issue.

Frans Bouma | Lead developer LLBLGen Pro