Repository generic method GetById using eager loading

ⅰ亾dé卋堺 提交于 2019-12-02 05:30:39

One possible way is to use FirstOrDefault with predicate over the DbSet with Includes. It's not hard to build manually a predicate using Expression.Equal method, but the main challenge is how to get the key property name. Luckily we can use some ObjectContext methods to do that, so the implementation could be like this (assuming we have access to the concrete DbContext instance):

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);
}

This is the update for Entity Framework Core 2.0. Also this method using the new metadata properties with EF to automatically get the first level navigation properties.

public virtual T Get(object id)
{
        var propertyName = "AddressId";

        //get all navigation properties defined for entity
        var navigationProps = _context.Model.FindEntityType(typeof(T)).GetNavigations();

        //turn those navigation properties into a string array
        var includeProperties = navigationProps.Select(p => p.PropertyInfo.Name).ToArray();

        //make parameter of type T
        var parameter = Expression.Parameter(typeof(T), "e");

        //create the lambda expression
        var predicateLeft = Expression.PropertyOrField(parameter, propertyName);
        var predicateRight = Expression.Constant(id);
        var predicate = Expression.Lambda<Func<T, bool>>(Expression.Equal(predicateLeft, predicateRight), parameter);

        //get queryable
        var query = _context.Set<T>().AsQueryable();

        //apply Include method to the query multiple times
        query = includeProperties.Aggregate(query, Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.Include);

        //return first item in query
        return query.FirstOrDefault(predicate);
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!