Disclaimer : I am unsure if what I am about to show here is a bridge too far in terms of bastardising the specification pattern ... it very well may be the case. However, Linq has provided a new paradigm that needs to be embraced, and sometimes that requires the tweaking of existing pratices and patterns.
Background Info
For some background on this article I recommend reading the following primers. I would never have to got to where I did without them. Please check out:
Implementing the Specification Pattern via Linq
[http://ubik.com.au/article/named/implementing_the_specification_pattern_with_linq]
Linq, the Specification Pattern and Encapsulation
[http://www.iridescence.no/post/Linq-the-Specification-Pattern-and-Encapsulation.aspx]
Implementing ORM-independent Linq queries
[http://rabdullin.com/implementing-orm-independent-linq-queries/]
The Goal
I wanted a flexible way to leverage the deferred execution power of Linq in my application. The logical place for this to occur was deep in the data access layer at the repository level. Also, as always, I wanted the ability to encapsulate my query logic into specifications and this became the real integration challenge with linq.
Specifications are easy to apply to existing in-memory collections - they fit that paradigm well. But at the lower level I knew linq could provide more power than what was previously possible with the traditional specification pattern. I wanted a way to leverage the deffered execution of Linq to drive my specifications for querying.
The Specification Class
My specification class is not dependent on any particular Linq to SQL provider. I chose to use Linq to NHibernate but that was a personal choice. I am quite sure that a switch to Linq-To-SQL would result in no modifications to any existing specifications. This provider agnostic specification implementation is a nice example of what a common language paradigm like Linq can provide.
Notice that the base abstract specification class handles all of the matching work for the specification. Any inheriting specification simply needs to specify their relevant MatchingCriteria. The SatisfyingElementFrom method (singular) simply enforces that a single result is returned. The bulk of the work is done in SatisfyingElementsFrom, which actually applies the criteria. Note that it is critical that the Matching criteria is of type Expression. This ensures we have access to the expression parsing power of Linq. Simply using a Func or a Predicate will break this implementation.
public abstract class Specification<T> where T : IEntity
{
public abstract Expression<Func<T, bool>> MatchingCriteria { get; }
public T SatisfyingElementFrom(IQueryable<T> candidates)
{
return SatisfyingElementsFrom(candidates).Single();
}
public IQueryable<T> SatisfyingElementsFrom(IQueryable<T> candidates)
{
return candidates.Where(MatchingCriteria).AsQueryable();
}
}
A simple specification
Below is the code for a simple specification implementation. Notice how it has no responsibility apart from specifying the criteria that it represents.
public class PersonById : Specification<Person>
{
private readonly Guid id;
public PersonById(Guid id)
{
this.id = id;
}
public override Expression<Func<Person, bool>> MatchingCriteria
{
get { return p => p.Id == id; }
}
}
Conclusion
So far I have demonstrated how to implement specification classes that have the potential to harness the power of Linq. Please follow the other parts of the series to see further implementation details - specifically the repository.
Whilst there is still ongoing debate about the merit of using regions, I have to admit that I have no strong leaning towards any side of the argument. However, I do need the ability to hide and show all of the regions in a class quickly and easily.
A trick that I first picked up when using VS2003 still works for me today and can quickly push you towards indifference in the debate as well.
This article written by Roland Weigelt (in 2003!) lists the code for some macros that can be simply assigned to a keyboard shortcut to help manage any regions you come across. Because, regardless of your stance on the issue, you will always come across regions somewhere.
Below I have assembled a short guide to installing and using the macros -
1. Copy all of the macro source code from the original article but only the module code itself (i.e ignoring the import statements and module declaration - these are added by VS automatically when you create a new module). The code below has been stolen from the original article and reproduced here for convenience.
' Toggles the current region surrounding the cursor
Sub ToggleParentRegion()
Dim objSelection As TextSelection
objSelection = DTE.ActiveDocument.Selection
Dim objPosition As EnvDTE.TextPoint
objPosition = objSelection.AnchorPoint
objSelection.SelectLine()
If (InStr(objSelection.Text.ToLower(), "#region") <> 0) Then ' Updated 14.08.2003
objSelection.MoveToPoint(objPosition)
DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
ElseIf (objSelection.FindText("#region", vsFindOptions.vsFindOptionsBackwards)) Then
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
Else
objSelection.MoveToPoint(objPosition)
End If
End Sub
' Expands all regions in the current document
Sub ExpandAllRegions()
DTE.ExecuteCommand("Edit.StopOutlining")
DTE.ExecuteCommand("Edit.StartAutomaticOutlining")
End Sub
' Collapses all regions in the current document
Sub CollapseAllRegions()
ExpandAllRegions()
Dim objSelection As TextSelection
objSelection = DTE.ActiveDocument.Selection
objSelection.StartOfDocument()
While (objSelection.FindText("#region"))
objSelection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn)
DTE.ExecuteCommand("Edit.ToggleOutliningExpansion")
objSelection.StartOfDocument()
End While
DTE.ActiveDocument.Selection.StartOfDocument()
End Sub
2. In Visual Studio (VS2008 in this example) open the Macros IDE (Alt-F11 or under Tools -> Macros)
3. In the Macros IDE, add a new macros module called RegionTools by right-clicking on MyMacros and select Add -> Add Module
4. Paste the code copied from above inside the module definition
5. Save and the close the Macros IDE
6. Now assign your keyboard shortcuts. Open the Options menu by opening Tools -> Options in Visual Studio
7. Under Environment in the tree menu (left hand side of the Options dialog), select Keyboard
8. Filter all of the available commands by typing RegionTools in the filter box

9. You should now see the 3 new macros that you added to the Macros IDE. And now you can assign them keyboard shortcuts at your whim. Personally I only use CollapseAllRegions (mapped to Ctrl+Shift+Num -) and ExpandAllRegions (mapped to Ctrl+Shift+Num +). But they are both of enormous benefit.
Now all that is left is for someone to tell me this has been built in to VS2008!
So after a lenghty layoff and many broken promises I am back into the blogging fold with a brand new screencast. I have been keen to demo Camtasia for a while and am pretty happy with the results. And it should make for a better end user experience because I am not a very good writer!
The video shows off some of the tricks, tools and techniques for TDD in .Net. It was cool to play with Gallio for the first time and I am loving its integration with Resharper. Very nice.
For best result watch the video in its original size (the quality if you do that is surprisingly good). To access the original size -
- Click the full screen button in the top right corner.
- Click the menu button in the bottom left corner.
- Then in the menu along the top of the screen click 'Original size'.
Alternatively, if you prefer to watch the video offline you can download from Viddler by clicking
here.
After a barrage of blog posts and primers from the guys on the other side of the fence, it appears that today might be the day that System.Web.MVC is released.
To say that I am excited would be an understatement. Mainstream acceptance and support (from the big machine) means that we can now propose this style of development without fear of recrimination from cowering/OSS averse decision makers. To me this is the most powerful component of this release as it is by no means revolutionary from a technology standpoint.
I have the perfect project for MVC sitting in the wings and I can now unleash. Thanks Microsoft for having the vision to support the concepts that we developers hold dear. I accept that things from MS will never be on the bleeding edge, but at least they are beginning to get a lot closer.
I can't wait. Bring on the CTP!
So they say that you learn something new everyday. They are correct today.
Digging through open source code is a great way to learn new tricks and I have been doing a fair bit of it lately - out of both necessity and curiosity. This is probably old hat to some but to me the following code is a bright and shiny hat of confusion:
public JobDetails GetNextJobToProcess()
{
//crazy for loop syntax here ...
for (;;)
{
BaseJobStore cachedJobStore = jobStore;
if (cachedJobStore == null)
return null;
JobDetails jobDetails = jobStore.GetNextJobToProcessOrWaitUntilSignaled(schedulerGuid);
if (jobDetails != null)
return jobDetails;
}
}
Turns out that the syntax represents an infinite for loop without any initialisation, conditions or increments. Might come in handy one day and these things are always good to know. I found a great article for explaining the intricacies of the for loop at Blackwasp.
Bonus points for anyone who can recognise the project the code belongs to!!!
I was a little bit upset when I discovered that persisting a DateTime object with NHibernate in SQL Server 2005 only stored values to second precision. This was unexpected as I thought that I would not lose that much (any?) information from my DateTime instance.
So I went to the internet with problem in hand and tried to find a nice little solution for me. It didn't happen definitively so I though I might write about my solution here. I think that may be what blogs are for.
Implementing NHibernate.UserTypes.IUserType
A custom user type seemed to be the best option so I politely introduced myself to IUserType. Implementing this interface enables NHibernate to perform custom persistence operations at my specification and I'll be damned if it isn't empowering to do so!
The code below has been snipped for brevity but the full implementation is available at the end of this article. Here are the juicy bits ....
public class PreciseDateTimeUserType : IUserType
{
#region IUserType Members
......
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
int ordinal = rs.GetOrdinal(names[0]);
if (rs.IsDBNull(ordinal))
{
return new NullPreciseDateTime();
}
else
{
long value = rs.GetInt64(ordinal);
return new PreciseDateTime(value);
}
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
long val = ((PreciseDateTime) value);
((IDbDataParameter) cmd.Parameters[index]).Value = val;
}
.....
#endregion
}
My PreciseDateTime class
The code above introduces PreciseDateTime - a class I have created to support this process. This class represents a DateTime by internally storing it as an Int64 in FileTimeUTC format. This is the key to providing the increased precision (just be aware that the values become unreadable in the database). The PreciseDateTime class looks like this ...
public class PreciseDateTime
{
protected static long NullValue = long.MinValue;
private long _dateTimeStorage;
public PreciseDateTime(long dateTimeLong)
{
_dateTimeStorage = dateTimeLong;
}
public bool IsNull
{
get { return _dateTimeStorage == NullValue; }
}
public PreciseDateTime Clone()
{
return new PreciseDateTime(this);
}
public static implicit operator long(PreciseDateTime preciseDateTime)
{
if (preciseDateTime.IsNull)
{
return NullValue;
}
else
{
return preciseDateTime._dateTimeStorage;
}
}
public static implicit operator DateTime?(PreciseDateTime preciseDateTime)
{
if (preciseDateTime.IsNull)
{
return null;
}
else
{
return
DateTime.FromFileTimeUtc(preciseDateTime._dateTimeStorage);
}
}
public static implicit operator PreciseDateTime(DateTime? dateTime)
{
return
new PreciseDateTime((dateTime.HasValue)
? dateTime.Value.ToFileTimeUtc()
: NullValue);
}
}
Notice how cool implicit operators are in this instance. Basically my code takes any DateTime? representation and implicitly converts it to a PreciseDateTime object without my intervention. This makes for more readable code and prevents errors that could be introduced by manual conversions. Use it like this ...
MyObject.PreciseDateTime = DateTime.Now;
Use with Castle ActiveRecord
To start using this implementation in Castle ActiveRecord you can simply do this (inserting your own namespace where appropriate) ...
private PreciseDateTime _created;
[Property(ColumnType = "Project.Domain.UserTypes.PreciseDateTimeUserType, Project.Domain")]
public virtual PreciseDateTime Created
{
get { return _created; }
set { _created = value; }
}
So I am now assured of not forgetting (again) how to implement custom user types for NHibernate and Castle ActiveRecord. If anything here is blatantly wrong please shout out - for everyone's sake.
If you crave more information about FileTimeUtc and what it represents go to the almighty MSDN
Full code for this article is available here :
PreciseDateTimeUserType.cs (3.71 kb)