3 回答
TA贡献1793条经验 获得超6个赞
控制器方法接收 aproduct_id和 a category_id,而不是 aProductGroupId
第一个问题是为什么该方法product_id在需要对ProductGroupId.
这听起来很糟糕的设计,但无论如何,让我们首先将其product_id转换为所需的ProductGroupId(这将花费我们额外的数据库查询):
int? productGroupId = await _context.Products
.Where(p => p.Id == product_id)
.Select(p => (int?)p.ProductGroupId)
.FirstOrDefaultAsync();
if (productGroupId == null)
{
// Handle non existing product_id
}
剩下的就是访问 LINQ to Entities 查询中的导航属性,EF Core 会将其转换为生成的 SQL 查询中的适当联接。不需要中间Product列表。
List<ProductInCategory> unCategorize = await _context.ProductsInCategories
.Where(pic => pic.Product.ProductGroupId == productGroupId)
.ToListAsync();
TA贡献1785条经验 获得超4个赞
我可以建议你想要的代码修复,但有一个更好的解决方案:不加载数据以.
在您的代码示例中,您正在从数据库加载数据,然后告诉 EF 删除加载的项目。那效率不高。应该没有理由加载数据,您应该能够简单地执行查询而无需加载数据。
据我所知,实体框架不能“有条件删除”(因为没有更好的名字),例如:
DELETE FROM People WHERE Name = 'Bob'
如果您想根据特定列值(实体的 ID 除外)删除项目,则不能依赖实体框架,除非您想加载数据(这会影响性能)。
这里有两个更好的选择:
1.自己执行SQL查询
context.Database.ExecuteSqlCommand(
"DELETE FROM Products WHERE ProductGroupId = " + product.ProductGroupId
);
这就是我一直这样做的方式。
旁注:我期待有关 SQL 注入的评论。需要明确的是:这里没有 SQL 注入的危险,因为product.ProductGroupId它不是字符串,其值由开发人员控制,而不是最终用户。
尽管如此,我确实同意使用 SQL 参数是一种很好的做法。但是在这个答案中,我想提供一个简单的示例来展示如何执行包含 SQL 的字符串。
2. 找一个可以不用加载就删除的库。
我只是在谷歌搜索时偶然发现了这一点。实体框架扩展似乎已经实现了条件删除功能:
context.Customers.Where(x => x.ID == userId).DeleteFromQuery();
在你的情况下,那将是:
_context.Products.Where(g => g.ProductGroupId == product.ProductGroupId).DeleteFromQuery();
旁注:
我一直使用 Code First,EF 总是自动为我生成级联删除。因此,当您删除父项时,其子项也会被删除。我不确定您的数据库是否已进行级联删除,但我假设默认 EF 行为(根据我的经验)。
- 3 回答
- 0 关注
- 195 浏览
添加回答
举报