Таблица в моей базе данных используется для хранения иерархии. Это достигается тем, что столбец представляет его родителя, который является внешним ключом для другой строки в той же таблице.
Другая функция в этой таблице - это столбец, ссылающийся на ветвь.
Ветка имеет разрешение на просмотр всех записей, связанных с этой записью (родитель или потомки, но не в боковом направлении).
Для этого я получу все сущности, связанные с веткой, а затем рекурсивно получу их дети, пока у меня нет списка сущностей, у которых нет детей. В этот момент я надеялся использовать метод DBContext «OnModelCreating» для извлечения последовательной цепочки объектов, пока она не достигнет верхнего уровня.
Это работает частично. Все работает, пока я не доберусь до метода OnModelCreating
, где он извлекает родительские объекты, пока не доберется до родительского объекта с BranchId.
Я предполагаю, что он использует кэшированный результат из строки marketsUnknownChildren = await _context.Markets.Where(x => x.BranchID.Equals(brancheID)).ToListAsync();
. Поскольку для родительского объекта «BranchID» установлено значение «null», метод «OnModelCreating» не находит никаких объектов и оставляет параметр «ParentMarket» в качестве «null».
Я проверил это, назначив различные уровни иерархии к ветви. Каждый раз он возвращает все записи, которые не имеют дочерних элементов и цепочки родительских объектов до уровня, который содержит ветвь.
Как мне:
перезагружать объекты с parentIds, но без parentObject
или предотвращать применение предложения where к родительскому объекту
или нет кэшировать результаты первого запроса?
Спасибо.
Market
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Threading.Tasks;
namespace TenantToolVmApi.Models
{
[Table("Markets")]
public class Market
{
[Key]
public int ID { get; set; }
[Column("Branch ID")]
public int? BranchID { get; set; }
[Column("ParentId")]
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public virtual Market? ParentMarket { get; set; }
[Column("Canada_Plus_MarketsID")]
public int Canada_Plus_MarketsID {get; set;}
[Column ("Name")]
public string Name { get; set; }
}
}
MarketContext
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace TenantToolVmApi.Models
{
public class MarketContext : DbContext
{
public MarketContext(DbContextOptions<MarketContext> options)
: base(options)
{
}
public DbSet<Market> Markets { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Market>()
.HasOne(u => u.ParentMarket);
}
}
}
MarketCotroller
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TenantToolVmApi.Models;
namespace TenantToolVmApi.Controllers
{
[Authorize]
[ApiController]
[Route("[controller]")]
public class MarketsController : ControllerBase
{
private readonly MarketContext _context;
public MarketsController(MarketContext context)
{
_context = context;
}
// GET: api/Markets
[HttpGet]
public async Task<ActionResult<IEnumerable<Market>>> GetMarketsItems()
{
string userName = HttpContext.User.Identity.Name;
PermissionController permissionController = new PermissionController(userName);
if (permissionController.HasNationalScope())
return await _context.Markets.ToListAsync();
else
{
int brancheID = permissionController.GetAccessibleBranches();
IEnumerable<Market> marketsHasNoChildren = new List<Market>();
List<int> addedIds = new List<int>();
IEnumerable<Market> marketsUnknownChildren;
IEnumerable<Market> marketsToCheckOnNextPass;
IEnumerable<Market> result;
marketsUnknownChildren = await _context.Markets.Where(x => x.BranchID.Equals(brancheID)).ToListAsync();
while (marketsUnknownChildren.Count() > 0)
{
marketsToCheckOnNextPass = new List<Market>();
foreach (Market market in marketsUnknownChildren)
{
result = await _context.Markets.Where(x => x.ParentId.Equals(market.ID)).ToListAsync();
if (result.Count() > 0)
marketsToCheckOnNextPass = marketsToCheckOnNextPass.Concat(result);
else if (!addedIds.Contains(market.ID))
{
marketsHasNoChildren = marketsHasNoChildren.Concat(new List<Market> { market });
addedIds.Add(market.ID);
}
}
marketsUnknownChildren = marketsToCheckOnNextPass;
}
ActionResult<IEnumerable<Market>> returnActionResults = marketsHasNoChildren.ToList();
return returnActionResults;
}
}
private bool MarketsExists(int id)
{
return _context.Markets.Any(e => e.ID == id);
}
}
}