Referencing Datasource as IQueryable (v 2.6)

Posts   
 
    
arash
User
Posts: 54
Joined: 16-Dec-2008
# Posted on: 17-Sep-2012 17:42:35   

Hi,

I'm facing an issue with the following query:

IQueryable<ProductsEntity> products = md.Products;
            IQueryable<CustomersEntity> customers = md.Customers;
            IQueryable<OrdersEntity> orders = md.Orders;

            var q = from p in products
                    select new
                    {
                        p.ProductId,
                        p.ProductName,
                        Sum = (
                            from o in orders
                            join c in customers on o.CustomerId equals c.CustomerId
                            where o.EmployeeId == p.CategoryId
                            select o.Freight).Sum()
                    };


            var list = q.ToList();

The generated sql query is :

Query: SELECT [LPLA_1].[ProductID] AS [ProductId], [LPLA_1].[ProductName], (SELECT SUM([LPA_L1].[Freight]) AS [LPAV_] FROM (SELECT [LPLA_2].[Freight] FROM ( [Northwind].[dbo].[Orders] [LPA_L2]  INNER JOIN [Northwind].[dbo].[Customers] [LPA_L3]  ON  [LPA_L2].[CustomerID] = [LPA_L3].[CustomerID]) WHERE ( ( ( [LPLA_2].[EmployeeID] = [LPLA_1].[CategoryID])))) [LPA_L1]) AS [Sum] FROM [Northwind].[dbo].[Products] [LPLA_1] 

With the following exception:

The multi-part identifier "LPLA_2.EmployeeID" could not be bound.
The multi-part identifier "LPLA_2.Freight" could not be bound.

I know that this query seems ridiculous and it has no meaning. I just provided it to be able to reproduce it using Northwind database.

But if I use DataSource2<TEntity> instead of IQueryable<TEntity>, every thing is fine:

DataSource2<ProductsEntity> products = md.Products;
            DataSource2<CustomersEntity> customers = md.Customers;
            DataSource2<OrdersEntity> orders = md.Orders;

            var q = from p in products
                    select new
                    {
                        p.ProductId,
                        p.ProductName,
                        Sum = (
                            from o in orders
                            join c in customers on o.CustomerId equals c.CustomerId
                            where o.EmployeeId == p.CategoryId
                            select o.Freight).Sum()
                    };


            var list = q.ToList();

For some reasons I need to reference the datasources as separate variables, so why referencing as IQueryable causes this error?

I'm using the flowing binaries:

SD.LLBLGen.Pro.ORMSupportClasses.NET20 "2.6.12.0829" SD.LLBLGen.Pro.DQE.SqlServer.NET20 "2.6.12.0312" SD.LLBLGen.Pro.LinqSupportClasses.NET35 "2.6.12.0829"

A sample application is attached.

Attachments
Filename File size Added on Approval
LLBLNorthwind.rar 156,517 17-Sep-2012 17:43.55 Approved
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 18-Sep-2012 06:21:20   

I reproduced it with the latest v2.6 (RTL 2.6.12.0829). It seems something related to the subquery. This still works:

IQueryable<ProductEntity> products = md.Product;
IQueryable<CustomerEntity> customers = md.Customer;
DataSource2<OrderEntity> orders = md.Order;

var q = from p in products
        select new
        {
            p.ProductId,
            p.ProductName,
            Sum = (
                from o in md
                join c in customers on o.CustomerId equals c.CustomerId
                where o.EmployeeId == p.CategoryId
                select o.Freight).Sum()
        };

This works as well:

IQueryable<ProductEntity> products = md.Product;
IQueryable<CustomerEntity> customers = md.Customer;         

var q = from p in products
        select new
        {
            p.ProductId,
            p.ProductName,
            Sum = (
                from o in md.Order
                join c in customers on o.CustomerId equals c.CustomerId
                where o.EmployeeId == p.CategoryId
                select o.Freight).Sum()
        };

The code that fails, I don't have a clue why it happens. All I know is that this is not the case on v3.x.

Leaving behind the fact that this seems to be unexpected, Is there any special reason why you would want to do it that way? I.e.: Can you live with a workaround? And... it's highly recommended to move up to one of the v3.x builds, since there are a lot of LINQ2LLBL improvements in there, some of they had been back-ported to v2.6, but not all.

David Elizondo | LLBLGen Support Team
arash
User
Posts: 54
Joined: 16-Dec-2008
# Posted on: 18-Sep-2012 08:52:46   

Hi, The reasons I use the query this way are described in the following post:

http://www.llblgen.com/TinyForum/Messages.aspx?ThreadID=21205&StartAtMessage=0&#119582

I apply various where conditions to the data source at run time and then I use the result data source which has type of IQueryable<T> in the linq query.

We are planning to do the upgrade in the future. We need an appropriate time to do the preparations for upgrading to 3.x version but unfortunately it is not possible for us to do it now.

Thanks.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 18-Sep-2012 09:31:43   

We'll have a look at why this fails in v2.6. I have no idea why if would fail like it does though...

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 18-Sep-2012 10:46:05   

The expression tree looks the same (but it's not small, so I used a tostring() compare). Will look where it tests for DataSource2 types.

(edit) The Join expression refers to different aliases in the IQueryable<T> tree after it's been processed for aliases / scopes. Bizarre. No code explicitly uses DataSource(2)<T>... confused Looking into it..

(edit) the IQueryable<T> handles the join method call..... twice, giving out new aliases twice, which messes up the aliases for the sources. Looking into why this is.

(edit) It refers to IDataSource, the interface implemented on DataSource(2)<T>. In v3.5 it at first makes the same error as in v2.6 but it carries on with the proper aliases it assigns the second time it evaluates the join tree, and it results in a proper query.

The duplicate evaluation comes from the fact that it sees the join expression as an in-memory candidate as there's no connection to a DB element, as the types of the sequence expressions are IQueryable<T>, not DataSource(2)<T>. As it's a 'type' which is an interface, there's no information available about the real type (DataSource2<T>).

Though thinking about it, the in-memory candidate finder is there to find elements which have to be evaluated in-memory, read from variables etc., before conversion can begin. An IQueryable<T> typed element isn't one of these.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39910
Joined: 17-Aug-2003
# Posted on: 18-Sep-2012 12:01:17   

Fixed. See attached dll.

I hope this fixes all issues with IQueryable<T> usage instead of DataSource(2)<T> usage. If not, let me know.

Attachments
Filename File size Added on Approval
SD.LLBLGen.Pro.LinqSupportClasses.NET35.zip 88,343 18-Sep-2012 12:01.23 Approved
Frans Bouma | Lead developer LLBLGen Pro
arash
User
Posts: 54
Joined: 16-Dec-2008
# Posted on: 19-Sep-2012 07:31:52   

Hi,

It seems the issue has been resolved, I'll check other queries to see if I run into other problems.

Thanks for your excellent support and quick responses simple_smile

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 19-Sep-2012 07:42:43   

We are glad the fix worked for you simple_smile Thanks for the feedback.

David Elizondo | LLBLGen Support Team