I have some queries that I use all the time (like get rows only of some specific type, or count something etc.). I’d like to organize them somehow (better then I currently do).
Currently I have them all in a static class
called Queries
which I don’t really like because it’s like a I-don’t-know-how-to-name-this-class.
Is there a preferred way for organizing predefined queries in Entity Framework by extending some types etc.?
As requested here is an example showing how I use it:
All of my queries:
public static class Queries
{
public static IEnumerable<Light> GetEnabledLights()
{
using(var context = new MyEntities())
{
return context.Lights.Where(l => l.Enabled);
}
}
}
Code using some query:
public static class LightsLoader
{
public static void LoadLights()
{
var enabledLights = Queries.GetEnabledLights().ToList();
if (enabledLights.Count == 0)
{
throw new InvalidOperationException("There are no enabled lights.");
}
// ... more code
}
}
Faking the query and testing the business logic:
[TestClass]
public class LightsLoaderTests
{
[TestMethod]
[ExpectedException(typeof(InvalidOperationException))]
public void TestNoEnableLights()
{
using(ShimContext.Create())
{
ShimQueries.GetEnabledLights = () => Enumerable.Empty<Light>();
LightsLoader.LoadLights();
}
}
}
But back to the question: I just thought Entity Framework might offer a better way for organizing queries then putting them all in a God-Class 😉
8
Extending the ORM Context is a good approach, but in a system with lots of predefined queries, I use to take another approach, using Extensions methods in order to group the related queries. Let me give an example:
The usage is kept simple like this:
var data = Context.Financial() // This returns a FinancialContextExtensions instance with all Financial grouped queries
.GetComplexReportData() // This returns the actual result for your query
.ToArray();
I create a file FinancialContextExtensions
:
public static partial class ContextQueryExtensions
{
public static FinancialContextExtensions Financial(this DataContext context)
{
return new FinancialContextExtensions(context);
}
}
public class FinancialContextExtensions : ContextExtensions
{
protected readonly DataContext Context;
public FinancialContextExtensions(DataContext context)
{
this.Context = context;
}
public IEnumerable<FinancialReportInfo> GetComplexReportData(DateTime dateBeing, DateTime dateEnd)
{
return from a in Context.AAA
join b in Context.BBB on ...
where ...
group ...
select new FinancialReportInfo { ... };
}
}
PS: I don’t know if this pattern has a name, but a I remember reading it on a site, don’t know what site though…
5
Sounds like you are organizing your code by what the code is and not the domain it applies to. As a developer working with the entity framework, I would expect you to have a derived DataContext
class with all your general CRUD operations. Since this DataContext is your gateway to the database, it would make sense to store the queries and methods that use them in your derived class. I suggest not exposing the literal query strings publicly, keep them private and create public methods that use them internally.