使用DBContext显式加载在通用存储库模式中

时间:2015-02-04 15:07:58

标签: c# entity-framework generics dbcontext

我们的context.Configuration.LazyLoadingEnabled = false; 这是我的参考:http://www.entityframeworktutorial.net/EntityFramework4.3/explicit-loading-with-dbcontext.aspx

我们的API中有一个方法可以获得一个包含所有子节点的实体:

[IsQuery]
[HttpGet]
public async Task<IEnumerable<Blog>> GetAllBlogs()
{
    return this.EntityProvider.Get(this.CachedReader, BlogCore.AllIncludes);
}

这些是包含的导航属性

public static Expression<Func<Blog, object>>[] AllIncludes = new Expression<Func<Blog, object>>[]
        {
            i => i.Community.Name,
            i => i.Categories.Select(c => c.Children),
            i => i.Categories.Select(c => c.Name),
            i => i.Categories.Select(c => c.Description),
            i => i.Submitter,
            i => i.Champion,
            i => i.Properties,
            i => i.Challenge.Name,
            i => i.Challenge.Description,
            i => i.Challenge.RestrictToSubmit,
            i => i.Challenge.Prize,
            i => i.Status.Name,
            i => i.Tags,
            i => i.Contributors,
            i => i.Watchers,
            i => i.Documents.Select(d => d.Form.Name),
            i => i.Documents.Select(d => d.Form.Fields.Select(f => f.Metadata)),
            i => i.Documents.Select(d => d.Responses.Select(r => r.Field.Metadata)),
            i => i.Documents.Select(d => d.Responses.Select(r => r.BlobReferences.Select(b => b.Blob))),
            i => i.StatusComments.Select(s => s.User),
            i => i.StatusComments.Select(s => s.Status.Name),
            i => i.StatusComments.Select(s => s.Status.StatusIcon.Blob),
            i => i.BlogThumb,
            i => i.BlogThumb.Blob
        };

我们也有映射类

public override void ExtendDomainModel([NotNull] IRepositoryMetadata metadata, [NotNull] EntityTypeConfiguration<Blog> map)
        {
            map.Property(p => p.DateSubmitted).IsRequired();
            map.Property(p => p.LastEdited).IsRequired();
            map.HasRequired(p => p.Status);
            map.HasRequired(p => p.Community);
            map.HasOptional(p => p.Challenge);
            map.HasOptional(p => p.Champion);
            map.HasRequired(p => p.Submitter);
            map.MapManyToMany(metadata, p => p.Contributors, "blogContributor", "blogID", "userID");
            map.MapManyToMany(metadata, p => p.Tags, "blogTag", "blogID", "tagID");
            map.MapManyToMany(metadata, p => p.Categories, "blogCategories", "blogID", "categoryID");
            map.MapManyToMany(metadata, p => p.Watchers, "blogWatchers", "blogID", "userID");
            map.MapManyToMany(metadata, p => p.Documents, "blogdocument", "blogID", "responseID");
            map.HasMany(p => p.StatusComments).WithRequired(p => p.Blog);
            map.HasAddedProperties(metadata, "blogProperty");
            map.HasOptional(p => p.BlogThumb).WithOptionalDependent().WillCascadeOnDelete();
        }

我的查询需要4秒。没有CategoriesDocuments以及StatusComments 这些需要20秒。在本地机器上。

使用SQL profiler我注意到有很多子查询获得二级属性。我想省略子查询。

然后转到通用方法并添加所有包含子项:

[NotNull]
public IQueryable<TEntity> Get(ICacheableReader reader, params Expression<Func<TEntity, object>>[] includes)
{
    return reader.Get<TEntity>(opt => opt.Include(includes));
}



/// <summary>Construct a query which retrieves all entities from the repository.</summary>
        /// <typeparam name="TEntity">The entity type.</typeparam>
        /// <param name="options">The entity query configuration.</param>
        /// <returns>Returns a deferred query.</returns>
        /// <exception cref="ObjectDisposedException">This reader has been disposed.</exception>
        public IQueryable<TEntity> Get<TEntity>(Action<IQueryConfig<TEntity>> options = null) where TEntity : class, IEntity
        {
            this.AssertAccessible();
            return this.ApplyOptions(this.Context.Set<TEntity>(), options);
        }

1 个答案:

答案 0 :(得分:2)

类似(对于第一级属性):

public IQueryable<TEntity> Get<TEntity>(
    Action<IQueryConfig<TEntity>> options = null, 
    IEnumerable<Expression<Func<TEntity, Object>>> includeProperties = null) where TEntity : class, IEntity
{
    this.AssertAccessible();
    IQueryable<TEntity> query = this.Context.Set<TEntity>();
    if ( includeProperties != null )
        query = includeProperties.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));

    return this.ApplyOptions(query, options);
}