Reputation: 139
I have these Domain Models
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; }
}
For example I would like to impliment method TestAsync, there I want to work with Topic object and related Posts objects.
Topic model I can get using async method and topicId as param.
public async Task<bool> TestAsync(int topicId)
{
var topic = await topicService.GetByIdAsync(topicId);
// posts ...
}
And I have two ways, how to get related posts. But, what the difference if I will use LazyLoading or just another async query?
// Example: 1 (LazyLoading)
var posts = topic.Posts;
// OR Example: 2 (Async method)
var posts = await postService.GetAllByTopicIdAsync(topicId);
So, I think that Example:1 will works synchronously, and also that I lose all the advantages of async/await code. But Example: 2 makes me think, that may be I dont know all charms of Lazy Loading:) Could anyone clarify what solution I should use and why? Thanks:)
Upvotes: 9
Views: 6093
Reputation: 4655
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);
}
Usage: var posts = await GetReferenceAsync(context, topic, e => e.Posts);
Upvotes: 2
Reputation: 456322
Lazy loading is always synchronous, which is unfortunate. EF Core, for example, with its async-first mentality, does not (yet) support lazy loading.
Other options are to either do a join (eager loading) as Peter suggested, which asynchronously performs a single query; or to do an explicit second asynchronous query. Which one you'd choose comes down to how your model is normally used.
Personally, I would choose to do the eager loading if the models are always used together, and do multiple asynchronous queries otherwise. I do not use lazy loading myself, though nothing would prevent it from working.
Upvotes: 14
Reputation: 5524
You should do neither. I am assuming your GetByIdAsync() is implemented like this.
public async Task<Topic> GetByIdAsync(int id)
{
return await context.Topics.FirstAsync(t=>t.Id == id);
}
You should change it to be
public async Task<Topic> GetByIdAsync(int id)
{
return await context.Topics.Include(t=>t.Posts).FirstAsync(t=>t.Id == id);
}
Upvotes: -1