实体框架 - 延迟加载或额外的异步/等待查询方法?

时间:2017-07-31 16:44:39

标签: c# asp.net entity-framework async-await lazy-loading

我有这些域模型

public class Topic
{
    public int TopicId { get; set; }

    public virtual ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }

    public int? TopicId { get; set; }
    public virtual Topic Topic { get; set; }
}

例如,我想暗示方法TestAsync,我想使用Topic对象和相关的Posts对象。

主题模型我可以使用async方法和topicId作为参数。

public async Task<bool> TestAsync(int topicId)
{
    var topic = await topicService.GetByIdAsync(topicId);

    // posts ...
}

我有两种方法,如何获得相关的帖子。 但是,如果我将使用LazyLoading或只是另一个异步查询,会有什么区别?

// Example: 1 (LazyLoading)
var posts = topic.Posts;

// OR Example: 2 (Async method)
var posts = await postService.GetAllByTopicIdAsync(topicId);

所以,我认为Example:1将同步工作,并且我失去了async / await代码的所有优点。 但是例子:2让我觉得,这可能是我不知道Lazy Loading的所有魅力:) 任何人都可以澄清我应该使用什么解决方案,为什么?感谢:)

3 个答案:

答案 0 :(得分:6)

延迟加载始终是同步的,这是不幸的。例如,EF Core具有异步优先心态,但尚未支持延迟加载。

其他选项是像Peter建议的那样进行连接(急切加载),异步执行单个查询;或者做一个明确的第二次异步查询。您选择哪一个取决于您的模型通常如何使用。

就个人而言,如果模型总是一起使用,我会选择进行急切加载,否则会进行多次异步查询。我自己不使用延迟加载,但没有什么能阻止它工作。

答案 1 :(得分:1)

        public async Task<TProperty> GetReferenceAsync<TEntity, TProperty>(DBContext context, TEntity entity, Expression<Func<TEntity, TProperty>> property)
        where TEntity : class, IIdentifiable where TProperty : class
        {
            var getProperty = property.Compile();
            var value = getProperty(entity);
            if (value != null) { return value; }

            await context.Entry(entity).Reference(property).LoadAsync();
            return getProperty(entity);
        }

用法:var posts = await GetReferenceAsync(context, topic, e => e.Posts);

答案 2 :(得分:-1)

你不应该这样做。我假设您的GetByIdAsync()是这样实现的。

public async Task<Topic> GetByIdAsync(int id)
{
        return await context.Topics.FirstAsync(t=>t.Id == id);
}

您应将其更改为

public async Task<Topic> GetByIdAsync(int id)
{
        return await context.Topics.Include(t=>t.Posts).FirstAsync(t=>t.Id == id);
}