LINQ to SQL tips and tricks #1
Being on the inside of a product team often leads to uncovering or stumbling upon lesser-known techniques, and here are a few little nuggets I found interesting – I have more if there is interest.
Loading a delay-loaded property
LINQ to SQL lets you specify that a property is delay-loaded, meaning that not retrieved as part of normal query operations against that entity. This is particularly useful for binary and large text fields such as a photo property on an employee object that is rarely used and would cause a large amount of memory to be consumed on the client, not to mention traffic between the SQL and application.
There are times, however, when you want all these binaries returned in a single query, say, for example, returning all the photos for the company photo intranet page:
var db = new NorthwindContext();
var loadOptions = new DataLoadOptions();
loadOptions.LoadWith<Employee>(e => e.Photo);
db.LoadOptions = loadOptions;
Multiple entity types from a single stored procedure
It is possible to return multiple entity types from a single stored procedure in LINQ to SQL, although this is not well known as the LINQ to SQL designer doesn’t support it. It is necessary to hand-edit the DBML and then use SQL Metal (or my T4 template) to produce the required method signature.
It is easier to write the code yourself and add it to the non-generated portion of your data context. If you imagine a stored procedure GetStaticData that looks like this:
CREATE PROCEDURE GetStaticData AS
SELECT * FROM Region
SELECT * FROM Categories
SELECT * FROM Territories
Then all you need to do is write a method signature that looks like this (the sequence of result type attributes must match the order in the stored procedure):
[Function(Name=@"dbo.DynamicContractsActiveBetween")]
[ResultType(typeof(Region))]
[ResultType(typeof(Category))]
[ResultType(typeof(Territory))]
public IMultipleResults GetStaticData() {
return (IMultipleResults) ExecuteMethodCall(this, (MethodInfo) MethodInfo.GetCurrentMethod()).ReturnValue;
}
Intercepting create, update and delete operations
There are times when it is useful to listen to events and perform your own logic, perhaps auditing or logging for some scenarios. The easiest way is to implement some specially-named methods on your data context, perform your action, then dispatch the call back to LINQ to SQL.
The format of these specially-named methods is [Action][Entity], and you should pass back control to LINQ to SQL using ExecuteDynamic[Action] where [Action] is either Insert, Update or Delete. One example of such usage might be:
partial class NorthwindContext {
partial void InsertEmployee(Employee instance) {
instance.CreatedBy = CurrentUser;
instance.CreatedAt = DateTime.Now;
ExecuteDynamicInsert(instance);
}
partial void UpdateEmployee(Employee instance) {
AuditEmployeeOwnerChange(instance);
instance.LastModifiedAt = DateTime.Now;
ExecuteDynamicUpdate(instance);
}
partial void DeleteEmployee(Employee instance) {
AuditDelete(instance, CurrentUser);
ExecuteDynamicDelete(instance);
}
}
Check out part 2 of LINQ to SQL tips
[)amien
4 responses