JDandChips
JDandChips

Reputation: 10100

.NET LINQ to Entities base where clause for generic Type

I am using Entity Framework to access my domain models, all of which implement an interface (IPublishable) that specifies properties to indicate whether an item has been published.

When accessing items from the front end I always want to filter out unpublished items. So, every time I write a query I'm doing something similar to this (where the following DbSets Objects1 and Objects2 both implement IPublishable

context.Objects1.Where( x => x.IsPublished ...).OrderBy( x => x.Id).ToList()
context.Objects2.Where( x => x.IsPublished ...).First()

What would be ideal is if I could inject the common Where() clause into all my queries within my web app OR if there was a way to write an extension method which I could include in each query.

I tried to create the extension method for all linq queries

public static IEnumerable<T> FrontEnd<T>(this DbSet<T> dbSet) where T : class {
  return dbSet.Cast<IPublishable>().Where( x => x.IsPublished ...).Cast<T>();
}

And use like this...

context.Objects1.FrontEnd().Where( x => ...).OrderBy(...

However I get the error "LINQ to Entities only supports casting EDM primitive or enumeration types"

I'm new to EF, so any information would be a great help. Thanks

Upvotes: 3

Views: 3056

Answers (2)

qujck
qujck

Reputation: 14580

UPDATED as per comments - this works

public static IQueryable<T> FrontEnd<T>(this DbSet<T> dbSet)
    where T : class, IPublishable
{
    return dbSet.Where(x => x.IsPublished);
}

and can be used like this:

context.Objects1.FrontEnd().Where( x => ...).OrderBy(...

You can try either of these options:

public static IQueryable<dynamic> FrontEnd(this DbSet<dynamic> dbSet)
{
    return dbSet.Where(x => (x as IPublishable).IsPublished);
}

or

public static IQueryable<T> FrontEnd<T>(this DbSet<T> dbSet)
    where T : class, IPublishable
{
    return dbSet.Where(x => x.IsPublished);
}

note:

the first option uses dynamic so is slower with the second option you have to specify the type in the call to FrontEnd() e.g.

context.Objects1.FrontEnd<Objects1>().Where( x => ...).OrderBy(...

Upvotes: 2

sthiers
sthiers

Reputation: 3531

I think LINQ to Entities does not know how to match the cast operator to SQL request. As a suggestion, you could try something like that:

IEnumerable<IPublishable> ReadPublishable(Expression<Func<DomainModelType, bool>> condition)

The expression act as a predicate. So you pass to the ReadPublishable function a predicate that filters the IPublishable objects you need. I tried successfully but only on simple predicates so, I do not know whether that works if you make use of "is" or "as" operators.

Upvotes: 0

Related Questions