C# 使用实体框架在IRepository模式中创建where或任意子句

C# 使用实体框架在IRepository模式中创建where或任意子句,c#,entity-framework,inversion-of-control,repository-pattern,C#,Entity Framework,Inversion Of Control,Repository Pattern,我从一个使用IRepository模式的同事那里接手了一个项目。我以前从未使用过它,因此在理解如何生成WHERE子句或ANY子句时遇到一些问题 以前我有以下代码,它使用DataContext存储库(实际实现,我可以在其中使用where子句): IQueryable<Office> officeList = repository.Offices; if (specification.CountryId > 0) {

我从一个使用IRepository模式的同事那里接手了一个项目。我以前从未使用过它,因此在理解如何生成
WHERE
子句或
ANY
子句时遇到一些问题

以前我有以下代码,它使用DataContext存储库(实际实现,我可以在其中使用where子句):

        IQueryable<Office> officeList = repository.Offices;

        if (specification.CountryId > 0)
        {
            officeList = repository.Offices.Where(c => c.CountryId == specification.CountryId);
        }
        if (specification.LetterSize != null)
        {
            officeList =
                officeList.Where(
                    c => c.OfficeProducts.Any(d => d.OfficeProductDetail.Size == (int)specification.LetterSize));
        }

        return officeList.ToList();
IQueryable officeList=repository.Offices;
如果(specification.CountryId>0)
{
officeList=repository.Offices.Where(c=>c.CountryId==specification.CountryId);
}
if(specification.LetterSize!=null)
{
公务员=
公务员,在哪里(
c=>c.OfficeProducts.Any(d=>d.OfficeProductDetail.Size==(int)specification.LetterSize));
}
return officeList.ToList();
我想了解如何使用IRepository模式让上面的代码片段工作。我曾尝试实现WHERE/查询,但未能使其工作

我的问题:

  • 如何在实践中实现WHERE/ANY语句,这样我就可以像上面的代码片段那样做
我的假设

public interface IRepository
    {
        T GetById<T>(long id) where T : class;
        void Create<T>(T entity) where T : class;
        void Update<T>(T entity) where T : class;
        void SaveOrUpdate<T>(T entity) where T : class;
        void Delete<T>(T entity) where T : class;

        IList<T> FindAll<T>(params OrderBy[] orders) where T : class;
        int Count<T>(Expression<Func<T, bool>> whereExpression) where T : class;
        bool Exists<T>(Expression<Func<T, bool>> whereExpression) where T : class;

        T FindFirst<T>(Expression<Func<T, bool>> whereExpression, params OrderBy[] orders) where T : class;
        PaginatedResult<T> Find<T>(Expression<Func<T, bool>> whereExpression, int pageIndex, int pageSize, params OrderBy[] orders) where T : class;

        void ExecuteNativeSQL(string sql);
    }
公共接口IRepository
{
T GetById(长id),其中T:class;
void Create(T实体),其中T:class;
无效更新(T实体),其中T:类别;
void SaveOrUpdate(T实体),其中T:class;
作废删除(T实体),其中T:类别;
IList FindAll(params OrderBy[]orders),其中T:class;
int Count(表达式whereExpression),其中T:class;
bool存在(表达式whereExpression),其中T:class;
T FindFirst(表达式whereExpression,参数OrderBy[]orders),其中T:class;
PaginatedResult Find(表达式whereExpression,int pageIndex,int pageSize,params OrderBy[]orders),其中T:class;
void executentiveSQL(字符串sql);
}
实现:

public class EFRepository : IRepository
    {
        private IDBFactory databaseFactory;
        private LetterAmazerContext dataContext;

        public EFRepository(IDBFactory databaseFactory)
        {
            this.databaseFactory = databaseFactory;
        }

        protected LetterAmazerContext DataContext
        {
            get { return dataContext ?? (dataContext = databaseFactory.Get()); }
        }

        public T GetById<T>(long id) where T : class
        {
            IDbSet<T> dbset = DataContext.Set<T>();
            return dbset.Find(id);
        }

        public void Create<T>(T entity) where T : class
        {
            IDbSet<T> dbset = DataContext.Set<T>();
            dbset.Add(entity);
        }

        public void Update<T>(T entity) where T : class
        {
            dataContext.Entry(entity).State = EntityState.Modified;
        }

        public void SaveOrUpdate<T>(T entity) where T : class
        {
            throw new NotImplementedException();
        }

        public void Delete<T>(T entity) where T : class
        {
            IDbSet<T> dbset = DataContext.Set<T>();
            dbset.Remove(entity);
        }

        public IList<T> FindAll<T>(params OrderBy[] orders) where T : class
        {
            IDbSet<T> dbset = DataContext.Set<T>();
            var query = dbset.Where(t => true);
            query = ApplyOrders<T>(query, orders);
            return query.ToList<T>();
        }

        public int Count<T>(Expression<Func<T, bool>> whereExpression) where T : class
        {
            IDbSet<T> dbset = DataContext.Set<T>();
            return dbset.Count<T>(whereExpression);
        }

        public bool Exists<T>(Expression<Func<T, bool>> whereExpression) where T : class
        {
            IDbSet<T> dbset = DataContext.Set<T>();
            return dbset.Count<T>(whereExpression) != 0;
        }

        public T FindFirst<T>(Expression<Func<T, bool>> whereExpression, params OrderBy[] orders) where T : class
        {
            IDbSet<T> dbset = DataContext.Set<T>();
            var query = dbset.Where(whereExpression);
            query = ApplyOrders<T>(query, orders);
            return query.SingleOrDefault<T>();
        }

        public PaginatedResult<T> Find<T>(Expression<Func<T, bool>> whereExpression, int pageIndex, int pageSize, params OrderBy[] orders) where T : class
        {
            IDbSet<T> dbset = DataContext.Set<T>();
            PaginatedResult<T> results = new PaginatedResult<T>();
            var query = dbset.AsExpandable().Where(whereExpression);
            query = ApplyOrders<T>(query, orders);
            results.Results = query.Skip<T>(pageIndex * pageSize).Take<T>(pageSize).ToList<T>();
            results.TotalItems = dbset.AsExpandable().LongCount(whereExpression);
            return results;
        }

        public void ExecuteNativeSQL(string sql)
        {
            DataContext.Database.ExecuteSqlCommand(sql);
        }

        private IQueryable<T> ApplyOrders<T>(IQueryable<T> query, params OrderBy[] orders)
        {
            if (orders == null || orders.Length == 0) return query;
            foreach (var order in orders)
            {
                query = query.OrderBy(order.ToString());
            }
            return query;
        }
    }
公共类eRepository:IRepository
{
私有工厂数据库工厂;
private LetterAmazerContext数据上下文;
公共eForepository(IDBFactory数据库工厂)
{
this.databaseFactory=数据库工厂;
}
受保护的LetterAmazerContext数据上下文
{
获取{return dataContext???(dataContext=databaseFactory.get());}
}
公共T GetById(长id),其中T:class
{
IDbSet dbset=DataContext.Set();
返回dbset.Find(id);
}
公共无效创建(T实体),其中T:class
{
IDbSet dbset=DataContext.Set();
添加(实体);
}
公共无效更新(T实体),其中T:class
{
dataContext.Entry(entity).State=EntityState.Modified;
}
public void SaveOrUpdate(T实体),其中T:class
{
抛出新的NotImplementedException();
}
公共作废删除(T实体),其中T:class
{
IDbSet dbset=DataContext.Set();
删除(实体);
}
公共IList FindAll(params OrderBy[]orders),其中T:class
{
IDbSet dbset=DataContext.Set();
var query=dbset.Where(t=>true);
查询=申请者(查询、订单);
返回query.ToList();
}
公共整数计数(表达式whereExpression),其中T:class
{
IDbSet dbset=DataContext.Set();
返回dbset.Count(whereExpression);
}
公共bool存在(表达式whereExpression),其中T:class
{
IDbSet dbset=DataContext.Set();
返回dbset.Count(whereExpression)!=0;
}
公共T FindFirst(表达式whereExpression,参数OrderBy[]orders),其中T:class
{
IDbSet dbset=DataContext.Set();
var query=dbset.Where(whereExpression);
查询=申请者(查询、订单);
返回query.SingleOrDefault();
}
公共分页结果查找(表达式whereExpression,int pageIndex,int pageSize,params OrderBy[]orders),其中T:class
{
IDbSet dbset=DataContext.Set();
PaginatedResult结果=新的PaginatedResult();
var query=dbset.AsExpandable().Where(whereExpression);
查询=申请者(查询、订单);
results.results=query.Skip(pageIndex*pageSize).Take(pageSize).ToList();
results.TotalItems=dbset.AsExpandable().LongCount(whereExpression);
返回结果;
}
public void executentiveSQL(字符串sql)
{
DataContext.Database.ExecuteSqlCommand(sql);
}
专用IQueryable应用程序(IQueryable查询,参数OrderBy[]订单)
{
if(orders==null | | orders.Length==0)返回查询;
foreach(订单中的var订单)
{
query=query.OrderBy(order.ToString());
}
返回查询;
}
}

您的存储库目前对任意表达式开放,包括实现无法计算的潜在表达式

一方面,这是一个潜在的风险,即无法交付与如此开放的合同相匹配的实现

另一方面,你为什么不把它再暴露一点呢:

public interface IRepository
{
    ...
    IQueryable<T> Query<T>();
}
公共接口IRepository
{
...
IQueryable查询();
}

公共类eRepository:IRepository
{
...
公共IQueryable查询()
{
返回DataContrxt.Set();
}
}
请注意,如果您决定这样做,大多数特定的查询方法就不再有意义了,因为这样的开放通用查询接口满足了大多数需求。

public class EFRepository : IRepository { ... public IQueryable<T> Query<T>() { return DataContrxt.Set<T>(); } }