#c# #entity-framework-core #ef-core-3.1 #self-reference #ef-core-5.0
#c# #entity-framework-core #ef-core-3.1 #самоссылка #ef-core-5.0
Вопрос:
Я хочу внедрить систему комментариев, это мой объект комментариев.
public class Comment
{
public int CommentId { get; set; }
public int? ParentId { get; set; }
public string Content { get; set; }
public DateTimeOffset DateCreated { get; set; }
public DateTimeOffset DateModified { get; set; }
public Comment Parent { get; set; }
public ICollection<Comment> Children { get; set; }
}
и это мои конфигурации в Fluent API
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Comment>(comment =>
{
comment.HasKey(c => c.CommentId);
comment.HasIndex(c => c.ParentId);
comment.HasOne(c => c.Parent)
.WithMany(c => c.Children)
.HasForeignKey(c => c.ParentId);
});
}
все в порядке, и я могу загрузить все записи с иерархией (включая родительские и дочерние элементы) с помощью этого кода
List<Comment> comments = await _db.Comments.Include(c => c.Children)
.ToListAsync();
но этот код загружает все элементы, такие как дочерние элементы. Но я хочу загрузить всех родителей, а затем их дочерних элементов, а затем внуков и ….
Я использую этот код для этого сценария
List<Comment> comments = await _db.Comments.Include(c => c.Children)
.Where(c => c.ParentId == null)
.ToListAsync();
и этот код просто загружает всех родителей со своими дочерними элементами, а не grand children и многое другое в иерархии.
Как мне написать этот запрос?
Комментарии:
1. Это очень сложный запрос, я рекомендую записать его в хранимую процедуру или табличную функцию на сервере и вместо этого запросить ее из EF. В EF нет понятия курсоров, и я полагаю, вы обнаружите, что они вам понадобятся. Или, по крайней мере, действительно точные запросы CTE.
2. Пожалуйста, ищите другие вопросы по иерархии LINQ или рекурсивному. Это постоянно повторяющаяся тема.
Ответ №1:
Я нашел решение для этого сценария.
public async Task<IActionResult> Index()
{
List<Comment> comments = await _db.Comments.AsNoTrackingWithIdentityResolution()
.Include(c => c.Children)
.ToListAsync();
// Structure Comments into a tree
List<Comment> commentsTree = comments.Where(c => c.ParentId == null)
.AsParallel()
.ToList();
return View(commentsTree);
}