EF包括其他实体(通用存储库模式)


72

我在Entity Framework Code First之上使用通用存储库模式。一切工作正常,直到我需要在查询中包含更多实体。我必须成功包含一个实体,但是现在我不知道如何包含多个实体。看看到目前为止我得到了什么:

public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
{
    var entityName = GetEntityName<TEntity>();
    return _objectContext.CreateQuery<TEntity>(entityName);
}

public IList<TEntity> GetQueryWithInclude<TEntity>(string toInclude) where TEntity : class
{
    var entityName = GetEntityName<TEntity>();
    return _objectContext.CreateQuery<TEntity>(entityName).Include(toInclude).ToList();
}

private string GetEntityName<TEntity>() where TEntity : class
{
    return string.Format("{0}.{1}", _objectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name));
}

我试图做但没用的是将字符串数组传递给函数,然后尝试将“包含”附加到查询顶部。我想知道如果我一次调用GetQueryWithInclude并传递一个实体名称(实际上是一个导航属性)来聚合查询结果该怎么办,但是我担心这可能会在每次调用时重复查询结果...您认为什么是使它正常工作的最佳方法?

提前致谢!

更新:

这是我要达到的目标的一个示例:

public IQueryable GetQueryWithIncludes(string[] otherEntities)
{
    var entityName = GetEntityName<TEntity>();
    //now loop over the otherEntities array 
    //and append Include extensions to the query
    //so inside the loop, something like: 
    _objectContext.GetQuery<TEntity>(entityName).Include(otherEntities[index]);
}

详细说明“在查询中包含更多实体”?你能举个例子吗?如果您有一个ObjectContext对象,则应该能够使用LinqToEntities查询对象或相关对象
gideon 2011年

@giddy:查看上面的更新。谢谢。
卡森

Answers:


140

仅在IQueryable上使用Include扩展。在EF 4.1组件中可用。如果您不想在上层引用该程序集,请在数据访问程序集中创建包装器扩展方法。

这里有例子:

public static IQueryable<T> IncludeMultiple<T>(this IQueryable<T> query, params Expression<Func<T, object>>[] includes)
    where T : class
{
    if (includes != null)
    {
        query = includes.Aggregate(query, 
                  (current, include) => current.Include(include));
    }

    return query;
}

您将使用它作为示例,例如:

var query = context.Customers
                   .IncludeMultiple(
                       c => c.Address,
                       c => c.Orders.Select(o => o.OrderItems));

该查询将向所有客户加载他们的地址和订单,每个订单将包含其订单项。


@Ladislav Mrnka:这正是我想要做的。我正在尝试使用Include扩展,但是我想创建一个通用方法,该方法可以在字符串数组中接受任意数量的导航属性,然后将那些包含查询实体的属性包括在内。请参阅上方的我的编辑/更新。
卡森

3
不要将版本与字符串一起使用。EF 4.1还提供带有lambda的强类型版本。
Ladislav Mrnka

@Ladislav Mrnka:好的,但是如何?你能举个例子吗?
卡森

如果您没有其他人的解决方案,我将在稍后发布示例。我目前正在使用iPhone编写文字,因此提供代码示例非常困难。
Ladislav Mrnka,2011年

1
@JeffBorden:IncludeMany是扩展方法(它是静态的,并且第一个参数使用this关键字),适用于所有实现类IQueryable。其中包括DbSet
拉迪斯拉夫·姆恩卡

3

//我在这里包括了最低要求。下面是如何使用它。

     IQueryable<File> xg= UnitOfWork.Files.GetAllLazyLoad(d => d.FileId == 1, 
            r => r.FileCategory);
//where r.FileCategory is a navigational property.

//Interface


    namespace Msh.Intranet.Repository.GenericRepoPattern
    {
        public interface IRepository<T> where T:class
        {

            IQueryable<T> GetAllLazyLoad(Expression<Func<T, bool>> filter, params Expression<Func<T, object>>[] children);

        }
    }



        namespace Msh.Intranet.Repository.GenericRepoPattern
        {
            /// <summary>
            /// The EF-dependent, generic repository for data access
            /// </summary>
            /// <typeparam name="T">Type of entity for this Repository.</typeparam>
            public class EFRepository<T> : IRepository<T> where T : class
            {
                public EFRepository(DbContext dbContext)
                {
                    if (dbContext == null)
                        throw new ArgumentNullException("dbContext");
                    DbContext = dbContext;
                    DbSet = DbContext.Set<T>();

                }

                protected DbContext DbContext { get; set; }

                protected DbSet<T> DbSet { get; set; }


                public virtual IQueryable<T> GetAllLazyLoad(Expression<Func<T, bool>> filter, params Expression<Func<T, object>>[] children) 
                {


                        children.ToList().ForEach(x=>DbSet.Include(x).Load());
                        return DbSet;
                }

            }
        }

1
看起来您的示例方法GetAllLazyLoad实际上正在急切地加载数据。据我了解,延迟加载将没有包含项,而是在首次访问数据时将其提取。您的方法似乎显示的是在创建对象时使用include提取数据。
Bennett Dill 2014年


0

对于实体框架,创建一个字符串列表来保存包含。请参阅以下示例代码

public virtual IQueryable<TObject> Filter(Expression<Func<TObject, bool>> filter,
                                              int skip = 0,
                                              int take = int.MaxValue,
                                              Func<IQueryable<TObject>, IOrderedQueryable<TObject>> orderBy = null,
                                              IList<string> incudes = null)
    {
        var _resetSet = filter != null ? DbSet.AsNoTracking().Where(filter).AsQueryable() : DbSet.AsNoTracking().AsQueryable();

        if (incudes != null)
        {
            foreach (var incude in incudes)
            {
                _resetSet = _resetSet.Include(incude);
            }
        }
        if (orderBy != null)
        {
            _resetSet = orderBy(_resetSet).AsQueryable();
        }
        _resetSet = skip == 0 ? _resetSet.Take(take) : _resetSet.Skip(skip).Take(take);

        return _resetSet.AsQueryable();
    }

有关更多详细信息,请参见下面的链接 http://bulletproofcoder.com/blog/using-include-in-a-generic-entity-framework-repository

实体框架核心中,我们将使用IIncludableQueryable。请参阅以下示例代码

        public virtual IQueryable<TObject> Filter(Expression<Func<TObject, bool>> filter,
                                              int skip = 0,
                                              int take = int.MaxValue,
                                              Func<IQueryable<TObject>, IOrderedQueryable<TObject>> orderBy = null,
                                              Func<IQueryable<TObject>, IIncludableQueryable<TObject, object>> include = null)
    {
        var _resetSet = filter != null ? DbSet.AsNoTracking().Where(filter).AsQueryable() : DbSet.AsNoTracking().AsQueryable();

        if (include != null)
        {
            _resetSet = include(_resetSet);
        }
        if (orderBy != null)
        {
            _resetSet = orderBy(_resetSet).AsQueryable();
        }
        _resetSet = skip == 0 ? _resetSet.Take(take) : _resetSet.Skip(skip).Take(take);

        return _resetSet.AsQueryable();
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.