使用预加载的存储库通用方法 GetById

ruu*_*uud 2 c# entity-framework repository repository-pattern

我正在使用实体框架,并希望在 Repository 类中创建通用的GetById方法并预先加载:

这是我使用延迟加载的方法:

public virtual TEntity GetById(object id)
  {
    return DbSet.Find(id);
  }
Run Code Online (Sandbox Code Playgroud)

我知道Find方法不支持急切加载,但是如何修改此方法以使用急切加载,因此我按如下方式使用此方法(例如):

_unitOfWork.MyRepository.GetById(includeProperties: "Users");
Run Code Online (Sandbox Code Playgroud)

Iva*_*oev 5

一种可能的方法是使用FirstOrDefaultwith 谓词而不是DbSetwith Includes。使用方法手动构建谓词并不难Expression.Equal,但主要挑战是如何获取关键属性名称。幸运的是,我们可以使用一些ObjectContext方法来做到这一点,因此实现可以如下所示(假设我们可以访问具体DbContext实例):

public virtual TEntity GetById(object id, params string[] includeProperties)
{
    var propertyName = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)DbContext).ObjectContext
        .CreateObjectSet<TEntity>().EntitySet.ElementType.KeyMembers.Single().Name;

    var parameter = Expression.Parameter(typeof(TEntity), "e");
    var predicate = Expression.Lambda<Func<TEntity, bool>>(
        Expression.Equal(
            Expression.PropertyOrField(parameter, propertyName),
            Expression.Constant(id)),
        parameter);

    var query = DbSet.AsQueryable();
    if (includeProperties != null && includeProperties.Length > 0)
        query = includeProperties.Aggregate(query, System.Data.Entity.QueryableExtensions.Include);
    return query.FirstOrDefault(predicate);
}
Run Code Online (Sandbox Code Playgroud)