3

I have this on my context object (constructor):

this.Configuration.UseDatabaseNullSemantics = true;

But even with this set, this query:

var query = (from i in _repo.Invoices
             join o in _repo.Orders on i.orderid equals o.orderid
             join o2 in _repo.Orders on o.linkedorderid equals o2.linkedorderid  into leftOrders
             from lo in leftOrders.DefaultIfEmpty()
             where invoiceIds.Contains(i.invoiceid)
             select new
             {
                i, lo
             }).ToList();

Returns this SQL:

SELECT 
    [Extent1].[invoiceid] AS [invoiceid], 
    [Extent1].[custid] AS [custid], 
    [Extent1].[orderid] AS [orderid], 
    [Extent1].[orderamount] AS [orderamount], 
    [Extent1].[invoiceamount] AS [invoiceamount], 
    [Extent1].[paidamount] AS [paidamount], 
    [Extent1].[paidstatus] AS [paidstatus], 
    [Extent1].[printdate] AS [printdate], 
    [Extent1].[updateddate] AS [updateddate]
    FROM   [dbo].[invoices] AS [Extent1]
    INNER JOIN [dbo].[orders] AS [Extent2] ON [Extent1].[orderid] = [Extent2].[orderid]
    LEFT JOIN [dbo].[orders] AS [Extent3] ON ([Extent2].[linkedorderid] = [Extent3].[linkedorderid]) OR (([Extent2].[linkedorderid] IS NULL) AND ([Extent3].[linkedorderid] IS NULL))
    WHERE [Extent1].[invoiceid] IN (3098489, 3123185, 3156838)

It's not hard to see that I'm getting a System.OutOfException error since I have tons of orders with linkedorderid equals NULL.

If I remove OR (([Extent2].[linkedorderid] IS NULL) AND ([Extent3].[linkedorderid] IS NULL)) query runs fine and returns all invoices that have or not children work orders...

Any idea how can I solve this ?

ebyrob
  • 667
  • 7
  • 24
Catinodeh
  • 301
  • 3
  • 16
  • 2
    Does this join make sense? I think that either `o.linkedorderid` or `o2.linkedorderid` should be something like `orderId`. Now you join orders with themselves. – Gert Arnold Mar 09 '16 at 19:59

2 Answers2

1

Does this work? If the posted query is correct when you remove the (or (is null and is null)) clause, then I think this will execute the same query. (This assumes there isn't a logic error in the joins, as suggested in other posts.)

var query = (from i in _repo.Invoices
    from o in _repo.Orders.Where(c => c.orderid == i.orderid)
    from o2 in _repo.Orders.Where(c => c.linkedorderid == o.linkedorderid).DefaultIfEmpty()                          
    where invoiceIds.Contains(i.invoiceid)
    select new
    {
       i, o2
    }).ToList();
Max Szczurek
  • 4,324
  • 2
  • 20
  • 32
0

The condition you see inside the generated SQL has nothing in common with UseDatabaseNullSemantics and is needed to handle correctly LEFT LOINs with nullable keys.

I think the problem you are experiencing is caused by a logical error in your query. IMO, the join condition

on o.linkedorderid equals o2.linkedorderid

should be

on o.linkedorderid equals o2.orderid

because normally the FK relates (joins) to the PK.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • Thanks for your comment, Ivan, but the logic is fine. – Catinodeh Mar 09 '16 at 21:24
  • Really? So it's supposed to join the record to itself, can't believe that. But you know better, good luck. – Ivan Stoev Mar 09 '16 at 21:28
  • 1
    @Catinodeh I also have a hard time believing the join passes a sanity check. Suppose all `linkedorderid` were unique (and not null). Then you'd just join two identical orders. If they aren't unique (ignoring the null issue) then you create Cartesian products for each value of `linkedorderid`, causing each invoice and each order to occur many times in the result set. I fail to see how that can be useful. Maybe you should explain what you're trying to achieve. – Gert Arnold Mar 09 '16 at 21:59
  • @GertArnold Please take my apologies, I haven't noticed your first comment, otherwise I wouldn't have posted this answer. – Ivan Stoev Mar 09 '16 at 23:43
  • No sweat :). I'm glad we both had the same doubts. – Gert Arnold Mar 10 '16 at 08:04