user6478921
user6478921

Reputation:

EF Context.Set<T>() Method

I want to get data with a condition as lambda expression like in.

public IEnumerable<T> GetBy(Func<T, bool> condition)
    {
        var test = Context.Set<StateInfo>().Where(p => p.CustomerID != null && p.CustomerID == 5);

        var test2= Context.Set<T>().Where(condition);
               .
               .
    }

When I am looking the test object SQL query It use where clause in It. But the test2 object query is like only select * from table. It gets all data from DB then use when method in code side. How can I get data with where clause because test2 query takes a long time with big datas. Only difference is one of the codes with generic class but the sql queries different. Thanks.

Upvotes: 4

Views: 2468

Answers (3)

xellan
xellan

Reputation: 101

The question was asked a long time ago, but it was relevant to me now and in search of a solution I did it

 public class Command<T> : IRepository<T>
 {
     public Context Context; 

     private IQueryable<T>? Reflection()
     {
         MethodInfo method = typeof(DbContext).GetMethod("Set", new Type[] { });
         MethodInfo generic = method.MakeGenericMethod(typeof(T));
         IQueryable<T>? queryable = ((IQueryable<T>)generic.Invoke(Context, null));
         return queryable;
     }
     public IEnumerable<T> Where(Func<T, bool> Expression) => Reflection()?.Where(Expression);
     public bool Any(Func<T, bool> Expression) => Reflection().Any(Expression);
     public T? FirstOrDefault(Func<T, bool> Expression) => Reflection().FirstOrDefault(Expression);
 }

Use

Command<People> people = new Command<People>();
var ss = people.Any(x => x.CompletedTasks == 1);
var re = people.Where(x => x.Name == x.Name).ToList();

Command<Product> product = new Command<Product>();
var res = product.Where(x => x.Name == x.Name).ToList();
var ssss = product.Any(x => x.Description == "");

Upvotes: 0

Adil Mammadov
Adil Mammadov

Reputation: 8696

Your condition is type of Func<T, bool>. When you look at overload of context.Set<T>().Where() you can see that, the one which takes Func<T, bool> returns IEnumerable<T> instaead of IQuerable<T>, because it takes all the data from the source, then applies filter. You should use Expression<Func<T, bool>> condition. Your method should be something like:

public IQueryable<T> GetBy<T>(Expression<Func<T, bool>> condition)
    where T : class
{
    return Context.Set<T>().Where(condition);               
}

Note: If you want to return IEnumerable after filtering you can just keep it like:

public IEnumerable<T> GetBy<T>(Expression<Func<T, bool>> condition)
    where T : class
{
    // Should also work without AsEnumerable()
    return Context.Set<T>().Where(condition).AsEnumerable();               
}

Upvotes: 4

Hamlet Hakobyan
Hamlet Hakobyan

Reputation: 33381

Use Expression instead.

Expression<Func<T, bool>> condition

When you use Func it cant be trunslated to SQL. You get the whole data the filter them inmemory. In case of Expression it will transleared to SQL and you will get filtered data from SQL server.

Upvotes: 1

Related Questions