I am working with the following SQL query:
SELECT
a.AppointmentId,
a.Status,
a.Type,
a.Title,
b.Days,
d.Description,
e.FormId
FROM Appointment a (nolock)
LEFT JOIN AppointmentFormula b (nolock)
ON a.AppointmentId = b.AppointmentId and b.RowStatus = 1
JOIN Type d (nolock)
ON a.Type = d.TypeId
LEFT JOIN AppointmentForm e (nolock)
ON e.AppointmentId = a.AppointmentId
WHERE a.RowStatus = 1
AND a.Type = 1
ORDER BY a.Type
I am unsure how to achieve the JOINs in LINQ. All my tables have foreign key relationships.
You may have to tweak this slightly as I was going off the cuff, but there are a couple of major things to keep in mind. If you have your relationships set up properly in your dbml, you should be able to do inner joins implicitly and just access the data through your initial table. Also, left joins in LINQ are not as straight forward as we may hope and you have to go through the DefaultIfEmpty syntax in order to make it happen. I created an anonymous type here, but you may want to put into a DTO class or something to that effect. I also didn't know what you wanted to do in the case of nulls, but you can use the ?? syntax to define a value to give the variable if the value is null. Let me know if you have additional questions...
If you want to preserve the (NOLOCK) hints, I have blogged a handy solution using extension methods in C#. Note that this is the same as adding nolock hints to every table in the query.
This linq method call (to Join) will generate the above Join.
These linq method calls (to GroupJoin, SelectMany, DefaultIfEmpty) will produce the above Left Join
The key concept here is that Linq's methods produce hierarchically shaped results, not flattened row-column shapes.
GroupBy
produces results shaped in a hierarchy with a grouping key matched to a collection of elements (which may not be empty). SQL'sGroupBy
clause produces a grouping key with aggregated values - there is no sub-collection to work with.GroupJoin
produces a hierarchical shape - a parent record matched to a collection of child records (which may be empty). Sql'sLEFT JOIN
produces a parent record matched to each child record, or a null child record if there are no other matches. To get to Sql's shape from Linq's shape, one must unpack the collection of child records withSelectMany
- and deal with empty collections of child records usingDefaultIfEmpty
.And here's my attempt at linquifying that sql in the question: