【发布时间】:2019-03-15 09:55:32
【问题描述】:
我正在开发一个已建立的(但可以更改,假设现有数据在任何更改后仍然存在)代码库并调查一些非常缓慢的删除。到目前为止,我只是成功地让事情变得更糟,所以我们到了。为了避免造成额外不必要的混乱,我已经取消了我在下面尝试的大部分更改。
有一个数据类 ProductDefinition,它模拟了一个相同的对象层次结构,类似于例如文件夹结构:每个 PD(根目录除外)都有一个父级,但就像一个文件夹可以有多个子级一样。
public class ProductDefinition
{
public int ID { get; set; }
// each tree of PDs should have a 'head' which will have no parent
// but most will have a ParentPDID and corresponding ParentPD
public virtual ProductDefinition ParentProductDefinition { get; set; }
public int? ParentProductDefinitionId { get; set; }
public virtual List<ProductDefinition> ProductDefinitions { get; set; }
= new List<ProductDefinition>();
[Required]
[StringLength(100)]
public string Name { get; set; }
// etc. Fields. Nothing so large you'd expect speed issues
}
在Context中已经明确声明了对应的表
public DbSet<ProductDefinition> ProductDefinitions { get; set; }
以及在 Context.OnModelCreating 上定义的 Fluent API 关系
modelBuilder.Entity<ProductDefinition>()
.HasMany(productDefinition => productDefinition.ProductDefinitions)
.WithOne(childPd => childPd.ParentProductDefinition)
.HasForeignKey(childPd => childPd.ParentProductDefinitionId)
.HasPrincipalKey(productDefinition => productDefinition.ID);
似乎已经尝试在 ProductDefinitionManager 类中确定删除
public static async Task ForceDelete(int ID, ProductContext context)
{
// wrap the recursion in a save so that it only happens once
await ForceDeleteNoSave(ID, context);
await context.SaveChangesAsync();
}
还有
private static async Task ForceDeleteNoSave(int ID, ProductContext context)
{
var pd = await context.ProductDefinitions
.AsNoTracking()
.Include(x => x.ProductDefinitions)
.SingleAsync(x => x.ID == ID);
if (pd.ProductDefinitions != null && pd.ProductDefinitions.Count != 0)
{
var childIDs = pd.ProductDefinitions.Select(x => x.ID).ToList();
// delete the children recursively
foreach (var child in childIDs)
{
// EDITED HERE TO CORRECTLY REFLECT THE CURRENT CODE BASE
await ForceDeleteNoSave(child, context);
}
}
// delete the PD
// mark Supplier as edited
var supplier = await context.Suppliers.FindAsync(pd.SupplierID);
supplier.Edited = true;
// reload with tracking
pd = await context.ProductDefinitions.FirstOrDefaultAsync(x => x.ID == ID);
context.ProductDefinitions.Remove(pd);
}
目前,上述解决方案“有效”,但是:
a) 需要 2 多分钟才能完成 b)似乎给 React 前端一个 502 错误(但见上文)。当然,FE 声称是 502
我的主要问题是:有没有办法提高删除速度,例如通过在 FluentAPI 中定义级联删除(我在尝试应用迁移时遇到了问题)?但我欢迎讨论可能导致 FE 报告 Bad Gateway 的原因。
【问题讨论】:
标签: c# ef-code-first entity-framework-core