Nice article Sam! What i'd like to point out, in your repo pattern is that, for me at least, having different methods conveys the intention of the code better than a generic filter. For example, with GetById, you just look for references of the method or search it to see where exactly is used. With a generic filter I think it would be harder to find, especially in big code bases, where it tries to bring a Product by Id and follow the logic of the code.
About Linq, a
Func<Product, bool> filteris in most cases (excepted linq-to-object) a bad choice. It will not leverage the capabilities of linq-to-entities or linq-to-nhibernate and the likes to perform the filter in the database. Instead, it will cause the data to be entirely loaded in the application memory and filtered in memory. It works only with Enumerable extensions, not with Queryable extensions.The fix is easy enough: use an
Expression<Func<Product, bool>> filter. And of course do not use it with a foreach loop, but with Linq Queryable extensions. A note about that should be added in your blog post.Actually, the pattern proposed by this blog post looks valid to me only if used with a Linq Queryable provider. Otherwise, how would it allow to perform the query filtering in the data store rather than in the application memory? Or am I missing something?