LINQ To SQL, Dynamic Querying & Fetching Strategies (cont)
I posted recently on using the Specification Pattern and utilizing the generic Expression<> and Func<> to dynamically change the criteria of SQL queries generated by the LINQ To SQL implementation. I promised to come back with an approach on enabling Eager Loading by implementing a Fetching strategy, that can be used with my Repository. Here’s the Fetching Strategy code (most of it).
1: public interface IFetchingStrategy
2: {
3: DataLoadOptions LoadOptions { get; }
4: }
5:
6: public interface IFetchingStrategy<TRole> : IFetchingStrategy
7: {
8:
9: }
10:
11: public interface ICustomerLoyaltyDiscount
12: {
13:
14: }
15:
16: public class CustomerLoyaltyDiscountFetchingStrategy :
17: IFetchingStrategy<ICustomerLoyaltyDiscount>
18: {
19: private readonly DataLoadOptions _loadOptions;
20:
21: public DataLoadOptions LoadOptions
22: {
23: get { return _loadOptions; }
24: }
25:
26: public CustomerLoyaltyDiscountFetchingStrategy()
27: {
28: _loadOptions = new DataLoadOptions();
29: _loadOptions.LoadWith<Customer>(c => c.Orders);
30: _loadOptions.LoadWith<Order>(o => o.OrderLines);
31: }
32: }
Most of the code above is self explanatory except perhaps for the interface ICustomerLoyaltyDiscount on line 11. This interface is used to describe a role in my repository so I can dynamically lookup Fetching Strategies that take that role as a generic parameter and use them to fetch data.
1: internal static void SimpleRepositoryDynamicFetching()
2: {
3: Specification<poco.Customer> simonsCoSpec =
4: new Specification<poco.Customer>
5: (c => c.Country == "Germany");
6:
7: DataContext ctx = GetContext();
8:
9: Repository<poco.Customer> customerRepository =
10: new Repository<poco.Customer>(ctx);
11:
12: var custs = customerRepository.
13: All<ext.ICustomerLoyaltyDiscount>(simonsCoSpec);
14:
15: foreach (var cust in custs)
16: {
17: Console.WriteLine("The Name of the Customer " +
18: "from Germany is {0}",
19: cust.CompanyName);
20: foreach (var order in cust.Orders)
21: {
22: Console.WriteLine("\tOrder Number {0}",
23: order.OrderID);
24: foreach (var orderLine in order.OrderLines)
25: {
26: Console.WriteLine("\t\tProduct ID {0} " +
27: "Amount {1}",
28: orderLine.ProductID,
29: (orderLine.Quantity *
30: orderLine.UnitPrice));
31: }
32: }
33: }
34: }
As you can see from the code above, when I call the Repository ALL method (as shown below), I use the overload that takes a generic parameter, indicating to the repository to look for a Fetching Strategy that also has this generic argument defined as its role.
1: public IList<T> All<TRole>(ISpecification<T> spec)
2: {
3: using (_context)
4: {
5: ext.IFetchingStrategy<TRole> strategy =
6: DynamicFetchingStrategyLoad<TRole>();
7: _context.LoadOptions = strategy.LoadOptions;
8: return GetTable().Where(spec.EvalPredicate).
9: ToList<T>();
10: }
11: }
The next time I post on this subject I will include the entire code, repository, specifications and fetching strategies.
4 comments








