LINQ: Common with IQueryable

I need to add some “search queries” to my C # .NET application. In principle, there will be many tables where they all have the same schema but contain different values.

I came across writing the same code over and over (there must be an OO way for this ..)

[edit - modified below to show more complete information] In any case, I would like to:

public List<GenericLookupE>         GetLookupItems( string what )
{
    // create db thing
    if ( "regions" == what )  return FetchLookup( db.lkRegions.AsQueryable() );
    if ( "partners" == what ) return FetchLookup( db.lkPartners.AsQueryable() );
    if ( "funders" == what )  return FetchLookup( db.lkFunders.AsQueryable() );

    return null; // or something more intelligent than that =)
}


private List<GenericLookupE>        FetchLookup<T>( IQueryable<T> lookup )
{
    return lookup.OrderBy( p => p.Sequence ).Select
    (   p => new GenericLookupE()
        {
            ID      = p.ID
            ,Label      = p.Label
            ,StateCode  = p.StateCode
            ,Sequence   = p.Sequence
        }
    ).ToList();
}

Of course, the problem is that the compiler does not know what p => p.Sequence is. Any ideas?

Thanks to everyone.

+5
source share
4 answers

Generic type restrictions are your friend. With a base type or interface containing a sequence:

where T : IMyBaseInterface

http://msdn.microsoft.com/en-us/library/bb384067.aspx

+3

, Sequence , .

interface ICommonInterface { // This is an awful name, please pick something better
    int Sequence { get }
}

private List<GenericLookupE> FetchLookup<T>( IQueryable<T> lookup ) where T : ICommonInterface {
    // Your stuff here
}
+2

.

- , , :

// Returns an expression of the form: p => new GenericLookupE
// { ID = p.ID, Label = p.Label, StateCode = p.StateCode, Sequence = p.Sequence }
// Can be written as a more generic 'auto-mapper', but
// this sample only solves your specific problem.
static Expression<Func<T, GenericLookupE>> GetLookupMapper<T>()
{ 
    var parameter = Expression.Parameter(typeof(T), "p");

    string[] properties = { "ID", "Label", "StateCode", "Sequence" };

    var bindings = from propName in properties
                   let source = Expression.Property(parameter, propName)
                   let target = typeof(GenericLookupE).GetProperty(propName)
                   select Expression.Bind(target, source);    

    var newExp = Expression.New(typeof(GenericLookupE));    
    var body = Expression.MemberInit(newExp, bindings);

    return Expression.Lambda<Func<T, GenericLookupE>>(body, parameter);
}

:

private List<GenericLookupE> FetchLookup<T>(IQueryable<T> lookup)
{
    return lookup.Select(GetLookupMapper<T>())
                 .OrderBy(p => p.Sequence)
                 .ToList();
}

, - .

+1

Regions, Partners Funders (ID, Label, StateCode Sequence). " ".

, "" , , , !

3 :

  • Regions, Partners Funders (, GenericLookupE) (, IGenericLookupE).
    • , .
    • , .Cast Select (. )
  • dynamic, ( , ).
  • ( )

Update

Here are some ways to make your database objects implement a common interface, depending on your structure:

Adding a base class (or interface) to all LINQ to SQL objects

Embedding an interface in a LINQ to SQL object using a partial class

0
source

All Articles