Repository generic method GetById using eager loading

后端 未结 3 574
傲寒
傲寒 2021-01-23 22:33

I am using Entity Framework and would like to create generic GetById method in Repository class with eager loading:

Here is my method which uses lazy-lo

相关标签:
3条回答
  • 2021-01-23 22:40

    Use This In Repository

    public IQueryable<T> FindByCondition(Expression<Func<T, bool>> expression)
        {
            return this.RepositoryContext.Set<T>().Where(expression).AsNoTracking();
        }
    

    and This In Action Method

    var User =  _IRepositoryWrapper.User.FindByCondition(x=>x.Id == id).Include(a=>a.Photos).FirstOrDefault();
    
    0 讨论(0)
  • 2021-01-23 22:42

    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);
    }
    
    0 讨论(0)
  • 2021-01-23 22:56

    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);
    }
    
    0 讨论(0)
提交回复
热议问题