如何更改我的查询或我的树节点模型以包括孙子和曾孙
How can I change my query or my Tree Node Model to include Grand-Children and Great-Grand-Children
我有一个基本上是树节点的实体模型:
[Table("bma_ec_categories")]
public class Category : INotifyPropertyChanged
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("category_id")]
public int CategoryId { get; set; }
[Column("parent_category_id")]
public int? ParentId { get; set; }
[Required]
[Column("category_name")]
[StringLength(50)]
public string Name { get; set; }
public Category Parent { get; set; }
public ICollection<Category> Children { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
在我的 DbContext 中我有:
modelBuilder.Entity<Category>()
.HasOne(p => p.Parent)
.WithMany(c => c.Children)
.HasForeignKey(k => k.ParentId);
我有一个查询使用 Category
:
public async Task<IEnumerable<EcommerceItemDto>> GetAllItemsAsync(User user, string category = "All", int page = 0, int pageSize = 9999)
{
IQueryable<Category> categories;
if (category == "All")
{
categories = _context.Categories
.Include(c => c.Children)
.Include(p => p.Parent)
.AsNoTrackingWithIdentityResolution();
}
else
{
categories = _context.Categories
.Where(n => n.Name == category)
.Include(c => c.Children)
.Include(p => p.Parent)
.AsNoTrackingWithIdentityResolution();
}
var p1 = new SqlParameter("@Custnmbr", SqlDbType.Char, 15) {Value = user.Custnmbr};
var dto = await _context.EcommerceItems
.FromSqlRaw($"SELECT * FROM [cp].[GetEcommerceItemsView] WHERE [CustomerNumber] = @Custnmbr",p1)
.Include(x => x.Category)
.Include(i => i.Images.OrderByDescending(d => d.Default))
.OrderBy(i => i.ItemNumber)
.Where(c => categories.Contains(c.Category) || categories.Any(x => x.Children.Contains(c.Category)))
.Skip(page * pageSize)
.Take(pageSize)
.AsNoTracking()
.ProjectTo<EcommerceItemDto>(_mapper.ConfigurationProvider)
.ToListAsync();
return dto;
}
如果使用默认的“All”调用该方法没有问题,但是如果使用实际的类别名称,我只会得到一个 Parent
和直接的 Children
。我可以做些什么来更改我的查询或模型以包含 Grand-Children
和 Great-Grand-Children
etc?
更新
我被要求添加我的 EcommerceItemDto
型号:
public class EcommerceItemDto
{
[Key]
public string ItemNumber { get; set; }
public string ItemDescription { get; set; }
[Column(TypeName = "text")]
public string ExtendedDesc { get; set; }
public bool? Featured { get; set; }
public string CategoryName { get; set; }
[Column(TypeName = "numeric(19, 5)")]
public decimal Price { get; set; }
[Column(TypeName = "numeric(19, 5)")]
public decimal QtyOnHand { get; set; }
public ICollection<EcommerceItemImagesDto> Images { get; set; }
}
我有 20 个左右的元数据属性,但我没有包含它们来保存 space。
在@SvyatoslavDanyliv 发表评论后,我找到了这个网站 article。以它为例,我将其添加到我的 DbContext:
public Task<List<Category>> AllChildren(string category) =>
Categories.FromSqlRaw(
@"WITH organization (category_id, category_name, title, parent_category_id, below) AS (
SELECT category_id, category_name, title, parent_category_id, 0
FROM dbo.bma_ec_categories
WHERE bma_ec_categories.category_name = {0}
UNION ALL
SELECT
e.category_id
,e.category_name
,e.title
,e.parent_category_id
,o.below + 1
FROM dbo.bma_ec_categories e
INNER JOIN organization o
ON o.category_id = e.parent_category_id)
SELECT * FROM organization", category)
.AsNoTrackingWithIdentityResolution()
.ToListAsync();
我将查询更改为:
public async Task<IEnumerable<EcommerceItemDto>> GetAllItemsAsync(User user, string category = "All", int page = 0, int pageSize = 9999)
{
List<Category> categories;
if (category == "All")
{
categories = await _context.Categories
.AsNoTrackingWithIdentityResolution()
.ToListAsync();
}
else
{
categories = await _context.AllChildren(category);
}
var p1 = new SqlParameter("@Custnmbr", SqlDbType.Char, 15) {Value = user.Custnmbr};
var dto = await _context.EcommerceItems
.FromSqlRaw($"SELECT * FROM [cp].[GetEcommerceItemsView] WHERE [CustomerNumber] = @Custnmbr",p1)
.Include(x => x.Category)
.Include(i => i.Images.OrderByDescending(d => d.Default))
.OrderBy(i => i.ItemNumber)
.Where(c => categories.Contains(c.Category))
.Skip(page * pageSize)
.Take(pageSize)
.AsNoTracking()
.ProjectTo<EcommerceItemDto>(_mapper.ConfigurationProvider)
.ToListAsync();
return dto;
}
现在一切正常,我很高兴。
我有一个基本上是树节点的实体模型:
[Table("bma_ec_categories")]
public class Category : INotifyPropertyChanged
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("category_id")]
public int CategoryId { get; set; }
[Column("parent_category_id")]
public int? ParentId { get; set; }
[Required]
[Column("category_name")]
[StringLength(50)]
public string Name { get; set; }
public Category Parent { get; set; }
public ICollection<Category> Children { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
在我的 DbContext 中我有:
modelBuilder.Entity<Category>()
.HasOne(p => p.Parent)
.WithMany(c => c.Children)
.HasForeignKey(k => k.ParentId);
我有一个查询使用 Category
:
public async Task<IEnumerable<EcommerceItemDto>> GetAllItemsAsync(User user, string category = "All", int page = 0, int pageSize = 9999)
{
IQueryable<Category> categories;
if (category == "All")
{
categories = _context.Categories
.Include(c => c.Children)
.Include(p => p.Parent)
.AsNoTrackingWithIdentityResolution();
}
else
{
categories = _context.Categories
.Where(n => n.Name == category)
.Include(c => c.Children)
.Include(p => p.Parent)
.AsNoTrackingWithIdentityResolution();
}
var p1 = new SqlParameter("@Custnmbr", SqlDbType.Char, 15) {Value = user.Custnmbr};
var dto = await _context.EcommerceItems
.FromSqlRaw($"SELECT * FROM [cp].[GetEcommerceItemsView] WHERE [CustomerNumber] = @Custnmbr",p1)
.Include(x => x.Category)
.Include(i => i.Images.OrderByDescending(d => d.Default))
.OrderBy(i => i.ItemNumber)
.Where(c => categories.Contains(c.Category) || categories.Any(x => x.Children.Contains(c.Category)))
.Skip(page * pageSize)
.Take(pageSize)
.AsNoTracking()
.ProjectTo<EcommerceItemDto>(_mapper.ConfigurationProvider)
.ToListAsync();
return dto;
}
如果使用默认的“All”调用该方法没有问题,但是如果使用实际的类别名称,我只会得到一个 Parent
和直接的 Children
。我可以做些什么来更改我的查询或模型以包含 Grand-Children
和 Great-Grand-Children
etc?
更新
我被要求添加我的 EcommerceItemDto
型号:
public class EcommerceItemDto
{
[Key]
public string ItemNumber { get; set; }
public string ItemDescription { get; set; }
[Column(TypeName = "text")]
public string ExtendedDesc { get; set; }
public bool? Featured { get; set; }
public string CategoryName { get; set; }
[Column(TypeName = "numeric(19, 5)")]
public decimal Price { get; set; }
[Column(TypeName = "numeric(19, 5)")]
public decimal QtyOnHand { get; set; }
public ICollection<EcommerceItemImagesDto> Images { get; set; }
}
我有 20 个左右的元数据属性,但我没有包含它们来保存 space。
在@SvyatoslavDanyliv 发表评论后,我找到了这个网站 article。以它为例,我将其添加到我的 DbContext:
public Task<List<Category>> AllChildren(string category) =>
Categories.FromSqlRaw(
@"WITH organization (category_id, category_name, title, parent_category_id, below) AS (
SELECT category_id, category_name, title, parent_category_id, 0
FROM dbo.bma_ec_categories
WHERE bma_ec_categories.category_name = {0}
UNION ALL
SELECT
e.category_id
,e.category_name
,e.title
,e.parent_category_id
,o.below + 1
FROM dbo.bma_ec_categories e
INNER JOIN organization o
ON o.category_id = e.parent_category_id)
SELECT * FROM organization", category)
.AsNoTrackingWithIdentityResolution()
.ToListAsync();
我将查询更改为:
public async Task<IEnumerable<EcommerceItemDto>> GetAllItemsAsync(User user, string category = "All", int page = 0, int pageSize = 9999)
{
List<Category> categories;
if (category == "All")
{
categories = await _context.Categories
.AsNoTrackingWithIdentityResolution()
.ToListAsync();
}
else
{
categories = await _context.AllChildren(category);
}
var p1 = new SqlParameter("@Custnmbr", SqlDbType.Char, 15) {Value = user.Custnmbr};
var dto = await _context.EcommerceItems
.FromSqlRaw($"SELECT * FROM [cp].[GetEcommerceItemsView] WHERE [CustomerNumber] = @Custnmbr",p1)
.Include(x => x.Category)
.Include(i => i.Images.OrderByDescending(d => d.Default))
.OrderBy(i => i.ItemNumber)
.Where(c => categories.Contains(c.Category))
.Skip(page * pageSize)
.Take(pageSize)
.AsNoTracking()
.ProjectTo<EcommerceItemDto>(_mapper.ConfigurationProvider)
.ToListAsync();
return dto;
}
现在一切正常,我很高兴。