Yet another LINQ error

Posts   
 
    
worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 28-Jul-2009 05:20:03   

I am writing a linq query and once again incorrect aliases are being generated. I have updated to the 17th july runtimes. Adapter templates.

Here is the trace:

Initial expression to process: value(SD.LLBLGen.Pro.LinqSupportClasses.DataSource21[Shivam.SCP.DAL.EntityClasses.TicketEntity]).Where(t => (t.IsActive = True)).WithPath(value(SD.LLBLGen.Pro.LinqSupportClasses.IPathEdge[])).GroupJoin(value(SD.LLBLGen.Pro.LinqSupportClasses.DataSource21[Shivam.SCP.DAL.EntityClasses.UserEntity]), t => t.AssignedToId, u => Convert(u.UserId), (t, tg) => new <>f__AnonymousType282(t = t, tg = tg)).SelectMany(<>h__TransparentIdentifier7 => <>h__TransparentIdentifier7.tg.DefaultIfEmpty(), (<>h__TransparentIdentifier7, g) => new <>f__AnonymousType2a2(<>h__TransparentIdentifier7 = <>h__TransparentIdentifier7, g = g)).OrderByDescending(<>h__TransparentIdentifier8 => <>h__TransparentIdentifier8.g.FirstName).ThenByDescending(<>h__TransparentIdentifier8 => <>h__TransparentIdentifier8.g.Surname).Select(<>h__TransparentIdentifier8 => <>h__TransparentIdentifier8.<>h__TransparentIdentifier7.t).Count() Method Enter: CreatePagingSelectDQ Method Enter: CreateSelectDQ Method Enter: CreateSelectDQ Method Enter: CreateSubQuery Method Enter: CreateSelectDQ Method Enter: CreateSelectDQ Method Enter: CreateSubQuery Method Enter: CreateSelectDQ Method Enter: CreateSelectDQ Generated Sql query: Query: SELECT [LPA_L2].[TicketId], [LPA_L2].[ProjectId], [LPA_L2].[AssignedToId], [LPA_L2].[CreatedById], [LPA_L2].[PriorityId], [LPA_L2].[StatusId], [LPA_L2].[CreatedOn], [LPA_L2].[TicketNo], [LPA_L2].[Subject], [LPA_L2].[IsActive] FROM [ClientPortal].[dbo].[Ticket] [LPLA_1] WHERE ( ( ( [LPA_L2].[IsActive] = @IsActive1))) Parameter: @IsActive1 : Boolean. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: True.

Method Exit: CreateSelectDQ Method Exit: CreateSubQuery Generated Sql query: Query: SELECT [LPA_L2].[TicketId], [LPA_L2].[ProjectId], [LPA_L2].[AssignedToId], [LPA_L2].[CreatedById], [LPA_L2].[PriorityId], [LPA_L2].[StatusId], [LPA_L2].[CreatedOn], [LPA_L2].[TicketNo], [LPA_L2].[Subject], [LPA_L2].[IsActive] FROM ( (SELECT [LPA_L2].[TicketId], [LPA_L2].[ProjectId], [LPA_L2].[AssignedToId], [LPA_L2].[CreatedById], [LPA_L2].[PriorityId], [LPA_L2].[StatusId], [LPA_L2].[CreatedOn], [LPA_L2].[TicketNo], [LPA_L2].[Subject], [LPA_L2].[IsActive] FROM [ClientPortal].[dbo].[Ticket] [LPLA_1] WHERE ( ( ( [LPA_L2].[IsActive] = @IsActive1)))) [LPA_L2] LEFT JOIN [ClientPortal].[dbo].[User] [LPA_L3] ON [LPA_L2].[AssignedToId] = [LPA_L3].[UserId]) Parameter: @IsActive1 : Boolean. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: True.

Method Exit: CreateSelectDQ Method Exit: CreateSubQuery Generated Sql query: Query: SELECT DISTINCT TOP 1 COUNT(*) AS [LPAV_] FROM (SELECT [LPA_L2].[TicketId], [LPA_L2].[ProjectId], [LPA_L2].[AssignedToId], [LPA_L2].[CreatedById], [LPA_L2].[PriorityId], [LPA_L2].[StatusId], [LPA_L2].[CreatedOn], [LPA_L2].[TicketNo], [LPA_L2].[Subject], [LPA_L2].[IsActive] FROM ( (SELECT [LPA_L2].[TicketId], [LPA_L2].[ProjectId], [LPA_L2].[AssignedToId], [LPA_L2].[CreatedById], [LPA_L2].[PriorityId], [LPA_L2].[StatusId], [LPA_L2].[CreatedOn], [LPA_L2].[TicketNo], [LPA_L2].[Subject], [LPA_L2].[IsActive] FROM [ClientPortal].[dbo].[Ticket] [LPLA_1] WHERE ( ( ( [LPA_L2].[IsActive] = @IsActive1)))) [LPA_L2] LEFT JOIN [ClientPortal].[dbo].[User] [LPA_L3] ON [LPA_L2].[AssignedToId] = [LPA_L3].[UserId])) [LPA_L1] Parameter: @IsActive1 : Boolean. Length: 0. Precision: 0. Scale: 0. Direction: Input. Value: True.

Method Exit: CreateSelectDQ Method Exit: CreatePagingSelectDQ: no paging. A first chance exception of type 'SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryExecutionException' occurred in SD.LLBLGen.Pro.ORMSupportClasses.NET20.DLL

Here is the exception message:

An exception was caught during the execution of a retrieval query: The multi-part identifier "LPA_L2.IsActive" could not be bound. The multi-part identifier "LPA_L2.TicketId" could not be bound. The multi-part identifier "LPA_L2.ProjectId" could not be bound. The multi-part identifier "LPA_L2.AssignedToId" could not be bound. The multi-part identifier "LPA_L2.CreatedById" could not be bound. The multi-part identifier "LPA_L2.PriorityId" could not be bound. The multi-part identifier "LPA_L2.StatusId" could not be bound. The multi-part identifier "LPA_L2.CreatedOn" could not be bound. The multi-part identifier "LPA_L2.TicketNo" could not be bound. The multi-part identifier "LPA_L2.Subject" could not be bound. The multi-part identifier "LPA_L2.IsActive" could not be bound.. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception.

Here is the stack trace

at SD.LLBLGen.Pro.ORMSupportClasses.RetrievalQuery.Execute(CommandBehavior behavior) at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchDataReader(IRetrievalQuery queryToExecute, CommandBehavior readerBehavior) at Shivam.SCP.DAL.DataAccessAdapter.FetchDataReader(IRetrievalQuery queryToExecute, CommandBehavior readerBehavior) in D:\Projects\Shivam Client Portal\Main\Source\SCP v1.0\Shivam.SCP.DAL\DataAccessAdapter.cs:line 292 at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchProjection(List1 valueProjectors, IGeneralDataProjector projector, IRetrievalQuery queryToExecute, Dictionary2 typeConvertersToRun) at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchProjection(List1 valueProjectors, IGeneralDataProjector projector, IEntityFields2 fields, IRelationPredicateBucket filter, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, IGroupByCollection groupByClause, Boolean allowDuplicates, Int32 pageNumber, Int32 pageSize) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProvider2.ExecuteValueListProjection(QueryExpression toExecute) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.ExecuteExpression(Expression handledExpression) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.Execute(Expression expression) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute[TResult](Expression expression) at System.Linq.Queryable.Count[TSource](IQueryable1 source) at Shivam.SCP.BL.Util.Ticket.Find(Int32 userId, Int32 projectId, Int32 statusId, PageRequestInfo info) in D:\Projects\Shivam Client Portal\Main\Source\SCP v1.0\Shivam.SCP.BL\Util\Ticket.cs:line 79 at Shivam.SCP.WebUI.Controllers.TicketController.GetTicketList() in D:\Projects\Shivam Client Portal\Main\Source\SCP v1.0\Shivam.SCP.WebUI.v2.0\Controllers\TicketController.cs:line 96

Here is the code that was executed (ex is thrown on the call to Count()): I have removed code that was not execute due to the arguments provided.

In the switch statement the "assignedto" switch is executed. Error occurs regardless of the sort direction.


public static IQueryable<TicketEntity> Find(int userId, int projectId, int statusId, PageRequestInfo info)
        {
            using (TransactionManager.DataAccessAdapter)
            {
                var ticketList = TransactionManager.Meta.Ticket.Where(t => t.IsActive == true);

                ticketList = ticketList.WithPath(path => path.Prefetch<PriorityEntity>(p => p.PriorityUsingPriorityId));

                IOrderedQueryable<TicketEntity> finalTicket;

                switch (info.SortBy.ToLower())
                {
                    case "subject":
                        finalTicket = info.SortDirection == SortOperator.Ascending ?
                            ticketList.OrderBy(p => p.Subject) :
                            ticketList.OrderByDescending(p => p.Subject);
                        break;
                    case "assignedto":
                        finalTicket = info.SortDirection == SortOperator.Ascending ?
                            (IOrderedQueryable<TicketEntity>)from t in ticketList join u in TransactionManager.Meta.User on t.AssignedToId equals u.UserId into tg from g in tg.DefaultIfEmpty() orderby g.FirstName, g.Surname select t :
                            (IOrderedQueryable<TicketEntity>)from t in ticketList join u in TransactionManager.Meta.User on t.AssignedToId equals u.UserId into tg from g in tg.DefaultIfEmpty() orderby g.FirstName descending, g.Surname descending select t;
                        break;
                    default: //name
                        finalTicket = info.SortDirection == SortOperator.Ascending ?
                            ticketList.OrderBy(p => p.CreatedOn) :
                            ticketList.OrderByDescending(p => p.CreatedOn);
                        break;
                }

                if (info.PageIndex == 0)
                    info.TotalItems = finalTicket.Count();//ex is thrown here

                return finalTicket.TakePage(info.PageIndex + 1, info.PageSize);
            }
        }

There is no entity inheritence in this scenario.

The Tables: I've commented the irrevelent relationships.

Ticket table:


CREATE TABLE [dbo].[Ticket](
    [TicketId] [int] IDENTITY(1,1) NOT NULL,
    [ProjectId] [int] NOT NULL,
    [AssignedToId] [int] NULL,
    [CreatedById] [int] NOT NULL,
    [PriorityId] [int] NOT NULL,
    [StatusId] [int] NOT NULL,
    [CreatedOn] [dbo].[Date] NOT NULL,
    [TicketNo] [nvarchar](32) NULL,
    [Subject] [nvarchar](256) NOT NULL,
    [IsActive] [dbo].[Flag] NOT NULL,
 CONSTRAINT [PK_Ticket] PRIMARY KEY CLUSTERED 
(
    [TicketId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
--ALTER TABLE [dbo].[Ticket]  WITH CHECK ADD  CONSTRAINT [FK_Ticket_Priority] FOREIGN KEY([PriorityId])
--REFERENCES [dbo].[Priority] ([PriorityId])
GO
--ALTER TABLE [dbo].[Ticket] CHECK CONSTRAINT [FK_Ticket_Priority]
GO
--ALTER TABLE [dbo].[Ticket]  WITH CHECK ADD  CONSTRAINT [FK_Ticket_Project] FOREIGN KEY([ProjectId])
--REFERENCES [dbo].[Project] ([ProjectId])
GO
--ALTER TABLE [dbo].[Ticket] CHECK CONSTRAINT [FK_Ticket_Project]
GO
--ALTER TABLE [dbo].[Ticket]  WITH CHECK ADD  CONSTRAINT [FK_Ticket_Status] FOREIGN KEY([StatusId])
--REFERENCES [dbo].[Status] ([StatusId])
GO
--ALTER TABLE [dbo].[Ticket] CHECK CONSTRAINT [FK_Ticket_Status]
GO
ALTER TABLE [dbo].[Ticket]  WITH CHECK ADD  CONSTRAINT [FK_Ticket_User] FOREIGN KEY([AssignedToId])
REFERENCES [dbo].[User] ([UserId])
GO
ALTER TABLE [dbo].[Ticket] CHECK CONSTRAINT [FK_Ticket_User]
GO
--ALTER TABLE [dbo].[Ticket]  WITH CHECK ADD  CONSTRAINT [FK_Ticket_User1] FOREIGN KEY([CreatedById])
--REFERENCES [dbo].[User] ([UserId])
GO
--ALTER TABLE [dbo].[Ticket] CHECK CONSTRAINT [FK_Ticket_User1]

User table:


CREATE TABLE [dbo].[User](
    [UserId] [int] IDENTITY(1,1) NOT NULL,
    [Username] [dbo].[Name] NOT NULL,
    [Password] [nvarchar](64) NOT NULL,
    [FirstName] [dbo].[Name] NOT NULL,
    [Surname] [dbo].[Name] NOT NULL,
    [Email] [dbo].[Email] NOT NULL,
    [IsActive] [dbo].[Flag] NOT NULL CONSTRAINT [DF_User_IsActive]  DEFAULT ((0)),
    [LastLogin] [dbo].[Date] NULL,
    [UpdatedOn] [dbo].[Date] NOT NULL,
    [UpdatedBy] [dbo].[CurrentUser] NOT NULL,
    [CreatedOn] [dbo].[Date] NOT NULL,
    [CreatedBy] [dbo].[CurrentUser] NOT NULL,
 CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [UserId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY],
 CONSTRAINT [IX_User] UNIQUE NONCLUSTERED 
(
    [Username] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

...the UDDTs i suppose u'll need


CREATE TYPE [dbo].[CurrentUser] FROM [nvarchar](64) NOT NULL
GO
CREATE TYPE [dbo].[Date] FROM [smalldatetime] NOT NULL
GO
USE [ClientPortal]
GO
CREATE TYPE [dbo].[Email] FROM [nvarchar](128) NOT NULL
GO
CREATE TYPE [dbo].[Flag] FROM [bit] NOT NULL
GO
CREATE TYPE [dbo].[Name] FROM [nvarchar](128) NOT NULL

defaults


CREATE DEFAULT [dbo].[CurrentDate] AS GetDate()
GO
CREATE DEFAULT [dbo].[CurrentUser] AS User_name()

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39861
Joined: 17-Aug-2003
# Posted on: 28-Jul-2009 09:54:38   

Will look into it. Please next time, cut the query to a query which illustrates the problem. I've now wade through all the code to find what's really going on. Also as you specify a prefetch path, check whether this is influencing the problem. If not, remove it so we don't have to worry about that. debugging expression trees which are very big is almost impossible, so the smaller the query the better. Also, you use defaultifempty() which has no meaning, yet this might be the cause (so we know where to look). If you remove it, does it influence the error? That's information we really want to know up front as it can save us a lot of time. wink

Frans Bouma | Lead developer LLBLGen Pro
worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 28-Jul-2009 10:43:21   

I thought that was how a left join was done in LINQ... wasn't working off an LLBL specific sample.

Ok leave it for now then, tomorrow morning I will try and drop the withpath and see what happens and play with removing DefaultIfEmpty and get back to you.

Today, I learn't the value of tracing simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39861
Joined: 17-Aug-2003
# Posted on: 28-Jul-2009 11:03:57   

When I use:


LinqMetaData metaData = new LinqMetaData(adapter);

var q1 = metaData.Order.Where(o => o.EmployeeId == 2);

var q = from o in q1
        join c in metaData.Customer on o.CustomerId equals c.CustomerId into oc
        from x in oc.DefaultIfEmpty()
        orderby x.CompanyName ascending 
        select o;

int count = q.Count();

I get:


SELECT DISTINCT TOP 1 COUNT(*) AS [LPAV_] 
FROM 
(
    SELECT  [LPA_L2].[OrderID] AS [OrderId], [LPA_L2].[CustomerID] AS [CustomerId], [LPA_L2].[EmployeeID] AS [EmployeeId], 
            [LPA_L2].[OrderDate], [LPA_L2].[RequiredDate], [LPA_L2].[ShippedDate], [LPA_L2].[ShipVia], [LPA_L2].[Freight], 
            [LPA_L2].[ShipName], [LPA_L2].[ShipAddress], [LPA_L2].[ShipCity], [LPA_L2].[ShipRegion], 
            [LPA_L2].[ShipPostalCode], [LPA_L2].[ShipCountry] 
    FROM    ([Northwind].[dbo].[Orders] [LPA_L2]  LEFT JOIN [Northwind].[dbo].[Customers] [LPA_L3]  
            ON  [LPA_L2].[CustomerID] = [LPA_L3].[CustomerID]) 
    WHERE ( ( ( ( [LPA_L2].[EmployeeID] = @EmployeeId1))))
) [LPA_L1]

Which is what I would have expected: the provider has a special visitor to remove the where clause in the join to avoid a derived table (as it otherwise doesn't know which side to refer to). Your sql query has that where clause still inside the join within a derived table.

However when I add the prefetch path node as you did, I can reproduce it:


LinqMetaData metaData = new LinqMetaData(adapter);

var q1 = metaData.Order.Where(o => o.EmployeeId == 2);
q1 = q1.WithPath(path => path.Prefetch<OrderDetailEntity>(p => p.OrderDetails));

var q = from o in q1
        join c in metaData.Customer on o.CustomerId equals c.CustomerId into oc
        from x in oc.DefaultIfEmpty()
        orderby x.CompanyName ascending 
        select o;

int count = q.Count();

produces:


SELECT DISTINCT TOP 1 COUNT(*) AS [LPAV_] FROM 
(
    SELECT  [LPA_L2].[OrderId], [LPA_L2].[CustomerId], [LPA_L2].[EmployeeId], [LPA_L2].[OrderDate], 
            [LPA_L2].[RequiredDate], [LPA_L2].[ShippedDate], [LPA_L2].[ShipVia], [LPA_L2].[Freight], 
            [LPA_L2].[ShipName], [LPA_L2].[ShipAddress], [LPA_L2].[ShipCity], [LPA_L2].[ShipRegion], 
            [LPA_L2].[ShipPostalCode], [LPA_L2].[ShipCountry] 
    FROM ((
            SELECT  [LPA_L2].[OrderId], [LPA_L2].[CustomerId], [LPA_L2].[EmployeeId], [LPA_L2].[OrderDate], 
                    [LPA_L2].[RequiredDate], [LPA_L2].[ShippedDate], [LPA_L2].[ShipVia], [LPA_L2].[Freight], 
                    [LPA_L2].[ShipName], [LPA_L2].[ShipAddress], [LPA_L2].[ShipCity], [LPA_L2].[ShipRegion], 
                    [LPA_L2].[ShipPostalCode], [LPA_L2].[ShipCountry] 
            FROM    [Northwind].[dbo].[Orders] [LPLA_1]  
            WHERE ((([LPA_L2].[EmployeeId] = @EmployeeId1)))
        ) [LPA_L2]  LEFT JOIN [Northwind].[dbo].[Customers] [LPA_L3]  
                ON  [LPA_L2].[CustomerId] = [LPA_L3].[CustomerID]
    )
) [LPA_L1]

And my guess is that the visitor to remove the where won't properly do its job as the prefetch path is embedded in the middle of the join.

When I move the prefetch path to a place OUTSIDE the join (where it should be, it's something you should add at the last minute to the very OUTSIDE of the query) ->


LinqMetaData metaData = new LinqMetaData(adapter);

var q1 = metaData.Order.Where(o => o.EmployeeId == 2);

var q = from o in q1
        join c in metaData.Customer on o.CustomerId equals c.CustomerId into oc
        from x in oc.DefaultIfEmpty()
        orderby x.CompanyName ascending 
        select o;

q = q.WithPath(path => path.Prefetch<OrderDetailEntity>(p => p.OrderDetails));

int count = q.Count();

it indeed produces proper SQL as the where clause is moved outside the join side properly:


SELECT DISTINCT TOP 1 COUNT(*) AS [LPAV_] 
FROM 
(
    SELECT  [LPA_L2].[OrderID] AS [OrderId], [LPA_L2].[CustomerID] AS [CustomerId], [LPA_L2].[EmployeeID] AS [EmployeeId], 
            [LPA_L2].[OrderDate], [LPA_L2].[RequiredDate], [LPA_L2].[ShippedDate], [LPA_L2].[ShipVia], [LPA_L2].[Freight], 
            [LPA_L2].[ShipName], [LPA_L2].[ShipAddress], [LPA_L2].[ShipCity], [LPA_L2].[ShipRegion], 
            [LPA_L2].[ShipPostalCode], [LPA_L2].[ShipCountry] 
    FROM    ([Northwind].[dbo].[Orders] [LPA_L2]  LEFT JOIN [Northwind].[dbo].[Customers] [LPA_L3]  
                    ON  [LPA_L2].[CustomerID] = [LPA_L3].[CustomerID]) 
    WHERE ( ( ( ( ( [LPA_L2].[EmployeeID] = @EmployeeId1)))))
) [LPA_L1]

Could you try for me please to move the Withpath to the bottom of the query? (as you're fetching entities anyway, it's the right place to put the statement, not at the beginning)

Frans Bouma | Lead developer LLBLGen Pro
worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 28-Jul-2009 11:51:17   

Hi Frans,

moving the withpath got rid if the exception however my result set is not being ordered.

If I call:

finalTicket.TakePage(info.PageIndex + 1, info.PageSize).ToList();

like that I get the expected SQL. However... if I return finalTicket and then from it run:


(from t in ticket
                             select new
                             {
                                 t.TicketNo,
                                 t.Subject,
                                 createdDate = t.CreatedOn.ToShortDateString(),
                                 assignTo = "Fred",//t.UserUsingAssignedToId.FirstName + " " + t.UserUsingAssignedToId.Surname,
                                 t.StatusId,
                                 t.TicketId,
                                 Status = t.StatusUsingStatusId.Name
                             }).ToList()


Things go a bit awry. I've noticed that referencing related entities automatically creates joins, that's awesome! But the ORDER BY goes out the window...

worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 28-Jul-2009 12:01:07   

I changed my switch to:


case "assignedto":
                        finalTicket = info.SortDirection == SortOperator.Ascending ?
                            ticketList.OrderBy(p => p.UserUsingAssignedToId.FirstName).OrderBy(p => p.UserUsingAssignedToId.Surname) :
                            ticketList.OrderByDescending(p => p.UserUsingAssignedToId.FirstName).OrderByDescending(p => p.UserUsingAssignedToId.Surname);
                        break;

and it's working! I guess LLBL figures out what type of join to do based on whether AssignedToId is null or not (i still get unassigned tickets in the resultset). This is awesome, I had no idea LINQ had these sort of smarts inbuilt, I can definately cut down on the amount of prefetching I am doing from now on. smile

This means I can do where clauses on joined tables (i'm assuming) too. OMG that was one of my main complaints about linq because I thought u had to put the where clause in the original LINQ statement. But now I can just go ticket.Where(p.StatusUsingStatusId.Name =="Closed") and llbl will do the rest (again, assuming). Sweet!

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39861
Joined: 17-Aug-2003
# Posted on: 28-Jul-2009 12:45:36   

worldspawn wrote:

I changed my switch to:


case "assignedto":
                        finalTicket = info.SortDirection == SortOperator.Ascending ?
                            ticketList.OrderBy(p => p.UserUsingAssignedToId.FirstName).OrderBy(p => p.UserUsingAssignedToId.Surname) :
                            ticketList.OrderByDescending(p => p.UserUsingAssignedToId.FirstName).OrderByDescending(p => p.UserUsingAssignedToId.Surname);
                        break;

and it's working! I guess LLBL figures out what type of join to do based on whether AssignedToId is null or not (i still get unassigned tickets in the resultset). This is awesome, I had no idea LINQ had these sort of smarts inbuilt, I can definately cut down on the amount of prefetching I am doing from now on. smile

simple_smile Yes, if the FK field is nullable, it automatically creates a left join simple_smile

This means I can do where clauses on joined tables (i'm assuming) too. OMG that was one of my main complaints about linq because I thought u had to put the where clause in the original LINQ statement. But now I can just go ticket.Where(p.StatusUsingStatusId.Name =="Closed") and llbl will do the rest (again, assuming). Sweet!

Glad it's working. Everything is now OK or are there still things left to look into?

Frans Bouma | Lead developer LLBLGen Pro
worldspawn avatar
worldspawn
User
Posts: 321
Joined: 26-Aug-2006
# Posted on: 28-Jul-2009 14:38:08   

Glad it's working. Everything is now OK or are there still things left to look into?

No that's it. All is well, thanks simple_smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39861
Joined: 17-Aug-2003
# Posted on: 28-Jul-2009 15:02:43   

worldspawn wrote:

Glad it's working. Everything is now OK or are there still things left to look into?

No that's it. All is well, thanks simple_smile

good sunglasses

Frans Bouma | Lead developer LLBLGen Pro