tags:

views:

542

answers:

3

So here is the scenario: i have a series of different repository classes that each can use an isolated data context, or a shared context. In the cases where an isolated context is being used i want to add a method to the base class that will allow me to specify the lambda as the parameter, have that expression be executed by the isolated context of the chosen repository and return an IQueryable result. How would the method signature look, and how to a pass the expression to the context?

I need the solution to be as generic as possible as any possible model object/table could be used.

Here is basically what i am looking to do:

IAssetRepository repo = new AssetRepository(true); // true indicates isolated context
var results = repo.ExecuteInContext<SomeType>(SomeTable.Where(x => 
                                              x.SomeProp.Equals(SomeValue)));
+7  A: 

Something like this:

public IEnumerable<T> ExecuteInContext<T>(
  Expression<Func<T,bool>> predicate)
{
  ... // do your stuff
  //eg
  Table<T> t = GetTable<T>();
  return t.Where(predicate);
}

or

public IEnumerable<T> ExecuteInContext<T>(
   IQueryable<T> src, Expression<Func<T,bool>> predicate)
{
  return src.Where(predicate);
}

Usage:

var r = repo.ExecuteInContext<SomeType>( 
          x => x.SomeProp.Equals(Somevalue));

or

var r = repo.ExecuteInContext(GetTable<T>(), 
          x => x.SomeProp.Equals(Somevalue));

Assumptions:

  1. Table can be derived from T, else you will need to pass the source too.
  2. You know how to modify the predicate expression if needed.
leppie
When trying your first suggestion, i get an error in compiling the Table<T> t = GetTable<T>(); line: T must be a reference type in order to use it as a parameter
Jason Miesionczek
nevermind, i got it. needed to add "where T : class" to the end of the method declaration.
Jason Miesionczek
Sorry, got hung up at work :)
leppie
+3  A: 

Check out PredicateBuilder - http://www.albahari.com/nutshell/predicatebuilder.aspx

This code will package up your where clause as Expression objects which you can pass about.

I've implemented the Repository pattern, and my flava is to give it a Fetch(ICriteria) method, which builds up the Where clause depending on the criteria supplied. Simple, but works for me.

Duncan
A: 

Here is a complete working sample how to pass LINQ expression as a parameter

http://www.kozlenko.info/blog/2009/12/08/passing-object-properties-as-a-parameter-using-linq-expressions/

using System;
using System.Linq.Expressions;
using System.Reflection;

namespace ConsoleTest
{
    public class Values
    {
        public int X { get; set; }
        public int Y { get; set; }

        public override string ToString()
        {
            return String.Format("[ X={0} Y={1} ]", X, Y);
        }
    }

    class Program
    {
        static void Main()
        {
            var values = new Values {X = 1, Y = 1};

            // pass parameter to be incremented as linq expression
            IncrementValue(values, v => v.X);
            IncrementValue(values, v => v.X);
            IncrementValue(values, v => v.Y);

            // Output is: [ X=3 Y=2 ]
            Console.Write(values);
        }

        private static void IncrementValue<T>(T obj, Expression<Func<T,int>> property)
        {
            var memberExpression = (MemberExpression)property.Body;
            var propertyInfo = (PropertyInfo)memberExpression.Member;
            // read value with reflection
            var value = (int)propertyInfo.GetValue(obj, null);
            // set value with reflection
            propertyInfo.SetValue(obj, ++value, null);
        }
    }
}
Maksym Kozlenko