这有效
var invoices = this.myContext.FilterByCustomer(this.myContext.Invoices, customerId);
它实现为:
public partial class MyContext : DbContext
{
public IQueryable<T> FilterByCustomer<T>(IQueryable<T> queryableEntityCollection, int customerId) where T : class, ICustomerEntity
{
// I need to query entities from MyContext here
// This implementation already works
}
}
但我想要这个
var invoices = this.myContext.Invoices.FilterByCustomer(customerId);
如果我在IQueryable(DbSet)上实现扩展方法,似乎我必须将MyContext
作为参数传递,我不喜欢。
public static IQueryable<T> FilterByCustomer<T>(this IQueryable<T> queryableEntityCollection, MyContext context, int customerId) where T : class, ICustomerEntity
{
// I need to query entities from MyContext here
// This WOULD work, I would be able to query other tables on 'context', but I don't like passing the context as parameter here
// I don't want this implementation
}
如何实现一个IQueryable扩展,它不要求我将上下文作为参数传递?
public IQueryable<T> FilterByCustomer<T>(IQueryable<T> queryableEntityCollection, int customerId) where T : class, ICustomerEntity
{
// I need to query entities from MyContext here, without passing MyContext as a parameter
// I want such implementation
}
这可能吗?
答案 0 :(得分:2)
你可以这样做,但它确实依赖于传递上下文但你不必传递集合。这假设您要过滤根DbSet<T>
而不是已过滤的IQueryable实例。
public static IQueryable<T> FilterByCustomer<T>(this DbContext context, int customerId) where T : class, ICustomerEntity
{
var queryableEntityCollection = context.Set<T>();
// rest of code that filters and returns something
}
称之为:
this.myContext.FilterByCustomer<Invoice>(customerId);
如果你真的想直接在DbSet上执行此操作并从该DbSet获取DbContext,那么请参阅前面的问题/答案。 Can you get the DbContext from a DbSet?
答案 1 :(得分:1)
这有可能吗?
是
Invoice
应为DbSet<TEntity>
,其源自IQueryable<TEntity>
所以:
public static IQueryable<T> FilterByLogin<T>(
this IQueryable<T> query,
int customerId)
where T : ICustomerEntity
{
var result = query.Where(cu => cu.CustomerId == customerId);
return result;
}
接口的最小值为:
public interface ICustomerEntity
{
public int CustomerId { get; }
}
用法:
var customers = this.myContext.Invoices
.FilterByLogin(customerId)
.ToList();
,其中
public class Invoice : ICustomerEntity
{
// etc
}
但是,实现详细信息从上下文中查询其他实体,因此方法中需要上下文的实例。
是(sorta,扩展方法然后离开dbcontext),但它很难看:
public static IQueryable<T> FilterByLogin<T>(
this MyContextType context
Func<IQueryable<T>> query,
int customerId)
where T : ICustomerEntity
{
var result = query(context)
.Where(cu => cu.CustomerId == customerId);
return result;
}
用法:
var customers = this.myContext
.FilterByLogin(c => c.Invoices, customerId)
.ToList();
它很难看,因为它在这个陈述中并不完全清楚返回的内容。
答案 2 :(得分:-1)
不要把它变成一种扩展方法。它看起来像一个存储库模式或任何你想要命名的模式。
所以你无论如何都需要将它分成自己的类。然后你也可以注入DbContext,使用它如下:
public class CustomerRepository<TCustomer>
where TCustomer : class, ICustomerEntity
{
public CustomerRepository(IYourContext context)
{
_context = context;
}
public IQueryable<TCustomer> FilterByCustomer(int customerId)
{
var customer = _context.Customers.Where(...);
var anotherEntity = _context.OtherEntities.Where(...);
}
}
或者,您可以在课程中注入必要的IQueryable<T>
:
public class CustomerRepository
{
public CustomerRepository(IQueryable<Customer> customers, IQueryable<OtherEntity> otherEntities)
{
_customers = customers;
_otherEntities = otherEntities;
}
public IQueryable<TCustomer> FilterByCustomer(int customerId)
{
var customer = _customers.Where(...);
var anotherEntity = _otherEntities.Where(...);
}
}