13.07.2015 Views

C# in Depth

C# in Depth

C# in Depth

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

LINQ to SQL323FROM [dbo].[NotificationSubscription] AS [t2]WHERE [t0].[ProjectID] = [t2].[ProjectID]) AS [count]FROM [dbo].[Defect] AS [t0]LEFT OUTER JOIN [dbo].[NotificationSubscription] AS [t1]ON [t0].[ProjectID] = [t1].[ProjectID]ORDER BY [t0].[DefectID], [t1].[NotificationSubscriptionID]That’s a pretty major change <strong>in</strong> the amount of SQL generated! There are two importantth<strong>in</strong>gs to notice. First, it uses a left outer jo<strong>in</strong> <strong>in</strong>stead of an <strong>in</strong>ner jo<strong>in</strong>, so we wouldstill see a defect even if it didn’t have anyone subscrib<strong>in</strong>g to its project. If you want aleft outer jo<strong>in</strong> but without the group<strong>in</strong>g, the conventional way of express<strong>in</strong>g this is touse a group jo<strong>in</strong> and then an extra from clause us<strong>in</strong>g the DefaultIfEmpty extensionmethod on the embedded sequence. It looks quite odd, but it works well. See the samplesource code for this chapter on the book’s website for more details.The second odd th<strong>in</strong>g about the previous query is that it calculates the count foreach group with<strong>in</strong> the database. This is effectively a trick performed by LINQ to SQL tomake sure that all the process<strong>in</strong>g can be done on the server. A naive implementationwould have to perform the group<strong>in</strong>g <strong>in</strong> memory, after fetch<strong>in</strong>g all the results. In somecases the provider could do tricks to avoid need<strong>in</strong>g the count, simply spott<strong>in</strong>g whenthe group<strong>in</strong>g ID changes, but there are issues with this approach for some queries. It’spossible that a later implementation of LINQ to SQL will be able to switch courses ofaction depend<strong>in</strong>g on the exact query.You don’t need to explicitly write a jo<strong>in</strong> <strong>in</strong> the query expression to see one <strong>in</strong> theSQL, however. We’re able to express our query <strong>in</strong> an object-oriented way, even thoughit will be converted <strong>in</strong>to SQL. Let’s see this <strong>in</strong> action.IMPLICIT JOINS: SHOWING DEFECT SUMMARIES AND PROJECT NAMESLet’s take a simple example. Suppose we want to list each defect, show<strong>in</strong>g its summaryand the name of the project it’s part of. The query expression is just a matterof a projection:// Query expressionfrom defect <strong>in</strong> context.Defectsselect new { defect.Summary, ProjectName=defect.Project.Name }-- Generated SQLSELECT [t0].[Summary], [t1].[Name]FROM [dbo].[Defect] AS [t0]INNER JOIN [dbo].[Project] AS [t1]ON [t1].[ProjectID] = [t0].[ProjectID]Notice how we’ve navigated from the defect to the project via a property—LINQ toSQL has converted that navigation <strong>in</strong>to an <strong>in</strong>ner jo<strong>in</strong>. It’s able to use an <strong>in</strong>ner jo<strong>in</strong>here because the schema has a non-nullable constra<strong>in</strong>t on the ProjectID column ofthe Defect table—every defect has a project. Not every defect has an assignee, however—theAssignedToUserID field is nullable, so if we use the assignee <strong>in</strong> a projection<strong>in</strong>stead, a left outer jo<strong>in</strong> is generated:// Query expressionfrom defect <strong>in</strong> context.Defectsselect new { defect.Summary, Assignee=defect.AssignedTo.Name }Licensed to Rhona Hadida

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!