views:

194

answers:

3

Here's an interesting problem. Is there a way to write some code using LINQ to SQL which is capable of performing a table UPDATE knowing only that the table it is given contains columns x, y, z but not knowing at compile time which table it is dealing with?

I have several tables in my DB schema which share some columns and I need to apply a set based UPDATE operation which is identical in its logical procedure regardless of which one of the tables we're dealing with.

Here's a simple example: say you have 3 tables which implement an adjacency model hierarchy (ie each row contains a primary key ID and a self-referencing parent ID column). Each of the tables also has a 'Disabled' boolean flag. When I disable an instance of any of these entities, it should cascade through the child items, i.e.

UPDATE MyTable SET Disabled = 1 WHERE ID = @ID or Parent_ID = @ID

I don't want to be writing these kind of LINQ statements for each entity, it violates DRY. It might seem trivial with this example, but as the example gets more complex you're duplicating increasing amounts of code. I'm sure it must be possible using an interface and perhaps generics, but I'm struggling to come up with an elegant solution.

+1  A: 

Simply create a base class for your entities and move the common properties to it as virtual properties. Override these properties in your entities and specify Column attributes on them. Here's a detailed example.

Ali Kazmi
+1  A: 

LINQ to SQL classes are just regular .NET classes that support an IQuery interface which they translate to SQL. (Not exactly a hand-wave)

You may be able to create your own IQuery implementation and point it to the generated LINQ to SQL IQuery implementation for the appropriate table. You add a property called 'TableName' and override 'Where' to support it.

This answer may not be a complete solution, but I hope it can point you in the right direction.

Matt Brunell
I don't need to override the LINQ to SQL query functionality, just write non-duplicated code to consume the existing IQueryable implementation.
Matt
A: 

Ali's solution would work (thanks for your input) but having done some more research my preferred solution is a 'mix-in' using interfaces and extension methods.

http://msdn.microsoft.com/en-us/vcsharp/bb625996.aspx

http://mikehadlow.blogspot.com/2008/05/interface-extension-methods-mixin.html

This has several advantages 1) I don't have to fiddle about with the autogeneration mechanism of the LINQ classes in VS2008 to support the new base class

2) It's not enforcing an inheritance hierarchy on my LINQ classes, I just add an interface to the partial class declaration and suddenly all this new, shared functionality arrives at the party!

3) If required, I could put the extension methods in their own namespace and clients could swap them out for other implementations.

Comments appreciated on this approach

Matt