ASP.NET+Entity Framework:如何简洁实现单个实体的预加载?
简洁预加载单个实体的解决方案
你可以通过以下几种方式简化单个实体的预加载操作:
1. 给仓库接口添加带Include参数的Get重载
直接在你的IRepository接口里新增一个支持预加载的Get方法,让仓库封装查询逻辑:
定义接口方法
public interface IRepository<T> where T : class { // 原有的Get方法(如果存在) T Get(Expression<Func<T, bool>> predicate); // 新增支持预加载的重载 T Get(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includes); }
实现该方法
在仓库的具体实现类(比如EfRepository<T>)中完成逻辑:
public T Get(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includes) { var query = _dbSet.AsQueryable(); foreach (var include in includes) { query = query.Include(include); } return query.Where(predicate).FirstOrDefault(); }
调用示例
现在可以用简洁的写法获取带预加载的单个实体:
var mi = _miRepository.Get(m => m.Id == input.Id, m => m.Type);
2. 编写扩展方法(无需修改原有仓库接口)
如果不想改动现有仓库的接口定义,给IRepository<T>写一个扩展方法即可:
public static class RepositoryExtensions { public static T GetWithInclude<T>(this IRepository<T> repo, Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includes) where T : class { var query = repo.GetAll(); foreach (var include in includes) { query = query.Include(include); } return query.Where(predicate).FirstOrDefault(); } }
调用示例
var mi = _miRepository.GetWithInclude(m => m.Id == input.Id, m => m.Type);
补充说明
你原来的写法_miRepository.GetAll().Include(m => m.Type).Where(m => m.Id == input.Id).First()其实不会真的查询全部数据——因为IQueryable是延迟执行的,最终生成的SQL只会查询符合条件的单条数据并预加载关联实体。但封装后的写法更简洁易读,也符合仓库模式的职责封装原则。
内容的提问来源于stack exchange,提问作者Ontkibbeling
相关产品推荐
相关产品推荐

