Question

For sake of brevity, assume I have a model named Participants like

public class Participant()
{
   public int? ID {get; set;}
   public string Name {get; set;}
   public DateTime JoinDate {get; set;}
   public string Address1 {get; set;}
   public string City {get; set;}
   public string County {get; set;}
}

public IList<Participant> SearchParticipants(Participant objParticipant)
{
   using (Db.Context())
   {
        //HOW CAN I ACHEIVE THIS? USING EF
        //WARNING PSEUDO-CODE / MAGIC FUNCTION (SearchMatches) BELOW

        return Db.Entities<Participant>().SearchMatches(objParticipant);
   }
}

Basically, I do not want to construct multiple .where(k => k.PropertyName) queries. I think certain PHP MVC frameworks have this, pass an object with certain properties filled in and one gets a array (in our case IList) of matching results from the DB.

Was it helpful?

Solution

You can do this using a combination of reflection, to loop through your properties, and dynamic linq to build the where predicates.

Below is a simple example as a starting point / proof of concept.

Currently it uses null as the value indicating that we don't want a where clause, but if you had a value type property (like int) then you could add an attribute like [FilterIgnore] or something and check that when you loop through the properties.

Make a new console application and replace program.cs with this then add the dynamic linq file from the sample to the project:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;

class MyObject
{
    // Some properties
    public string PropertyA { get; set; }
    public string PropertyB { get; set; }
    public DateTime? PropertyC { get; set; }

    static void Main(string[] args)
    {
        // Our repository
        var list = new List<MyObject>() {
                new MyObject() { PropertyA = "test"} ,
                new MyObject() { PropertyB = "test"} ,
                new MyObject() { PropertyC = DateTime.Today} ,
                new MyObject() { PropertyC = DateTime.Today,
                                 PropertyA = "test"} 
            };

        // Loop through the filtered results
        // (calling our GetByExample method with a
        // new object with a property set)
        foreach (var obj in 
                 GetByExample(list,
                              new MyObject() { PropertyC = DateTime.Today }))
        {
            // Write some output so we can see it working
            Console.WriteLine("Found object");
            Console.WriteLine(obj.PropertyA);
            Console.WriteLine(obj.PropertyB);
            Console.WriteLine(obj.PropertyC);
        }

        // Wait for the user to press a key before we close
        Console.ReadKey();
    }

    static IQueryable<MyObject> GetByExample(List<MyObject> objects,
                                             MyObject filterObj)
    {
        // Create our query variable that we'll add to
        var filteredObjects = objects.AsQueryable();

        // Loop through each property on this object
        foreach (var prop in filterObj.GetType().GetProperties())
        {
            // Get the value of this property
            var propVal = prop.GetValue(filterObj, null);

            if (propVal != null)
            {
                // If the property isn't null add a where clause
                filteredObjects =
                    filteredObjects.Where(string.Format("{0} = @0",
                                                        prop.Name),
                                          propVal);
            }
        }

        return filteredObjects;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top