Strange query behaviour

Posts   
 
    
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 03-May-2008 21:25:08   

Hi Frans

I've upgraded to the new 2.6 beta and this query now does something very odd:

var meta = new LinqMetaData(adapter);
var query = from o in meta.Order
        where o.CustomerId == "ALFKI"
        select o.Customer;

Although this query produces the correct number of CustomerEntity objects, all their fields appear to be empty.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 03-May-2008 22:09:46   

Huh? Hmm...

I have a lot of tests which check data, so the entity fetching does work, I'll check it out.

(edit) indeed! frowning

Very strange, will check it out. (tomorrow or monday). That routine uses a custom projector, however that hasn't been changed in a while... likely this hasn't worked for a long time rage (as the tests on this just tested the # of rows).

Doing: var q = from c in nw.Customers select c.Orders; does work though, the orders do have values.

Frans Bouma | Lead developer LLBLGen Pro
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 03-May-2008 22:27:19   

Possibly related, but calling .Count() on the same query causes an aliasing exception:

The multi-part identifier "LPA_1.CustomerID" could not be bound.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 03-May-2008 22:47:32   

I don't think that's related. So the query which fails too is: var query = (from o in meta.Order where o.CustomerId == "ALFKI" select o.Customer).Count();

?

Frans Bouma | Lead developer LLBLGen Pro
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 03-May-2008 23:13:31   

Yes, that's correct.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 05-May-2008 11:03:30   

The empty entity issue is fixed in the next build. It was caused by the fact that this query is a special case: it's a hierarchical fetch but the root type is completely not present in the end result. The projector tried to project the customer into a customer entity, which didn't set any fields and added an empty entity as the result.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 05-May-2008 11:39:24   

The count error is an interesting one.

Say I have this query:


LinqMetaData metaData = new LinqMetaData(adapter);
var count = (from o in metaData.Order
             where o.EmployeeId == 2
             select new
             {
                o.Customer
             }).Distinct().Count();

The distinct should be applied to the set of customers. So the result should be 62, not 110. However the customer projection is a nested set (as you first have to fetch the orders when you can fetch the customers), which isn't possible as the count is a db aggregate so the projection is inside a query, ran inside the db. simple_smile

I think I can solve this by removing an optimization with Count() (or CountRow): now it simply replaces the projection with count(). So doing: var count = (from c in metaData.Customers select c).Count(); simply does: SELECT COUNT(*) FROM Customers

To solve it it should do: SELECT COUNT(*) FROM (SELECT ... FROM Customers)

So the query it aggregates on should be folded into a derived table. The distinct is then placed inside the derived table. It can be a bit clever when to do this, and when to simply replace the projection. I'll add some code for this in the next build.

To work around the two glitches, rewrite the query a bit so you don't need the nested set of customers, but fetch the customers directly and filter on order.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 05-May-2008 11:59:47   

Count is now doing OK. Fixed in next build.

There will be a difference in numbers though: var q = (from o in md.Orders where o.EmployeeId ==2 select o.Customer).Count(); this will return 110 but var q = from o in md.Orders where o.EmployeeId ==2 select o.Customer;

and then enumerate over q will result in 62 customers. This is due to the fact that 'distinct' filtering on entities is performed on entity fetches, but the nested query in the first query is never executed, and the implicit distinct filtering is therefore never applied.

Frans Bouma | Lead developer LLBLGen Pro
Jez
User
Posts: 198
Joined: 01-May-2006
# Posted on: 05-May-2008 12:19:15   

Otis wrote:

This is due to the fact that 'distinct' filtering on entities is performed on entity fetches, but the nested query in the first query is never executed, and the implicit distinct filtering is therefore never applied.

This makes sense, although I could see it being confusing. Maybe a note in the documentation about this sort of query could be beneficial.

Anyway, thanks for fixing it simple_smile