猿问

如何根据不同对象类型的另一个列表从数据库中获取列表?

我有这两个模型:


public class Product

{

    public int Id { get; set; }

    public int ProductGroupId { get; set; }

    public int ProductGroupSortOrder { get; set; }

    // ... some more properties

    public ICollection<ProductInCategory> InCategories { get; set; }

}


public class ProductInCategory

{

    public int Id { get; set; }

    public int ProductId { get; set; }

    public int ProductCategoryId { get; set; }

    public int SortOrder { get; set; }


    // Nav.props.:

    public Product Product { get; set; }

    public ProductCategory ProductCategory { get; set; }

}

一些Products 通过属性组合在一起ProductGroupId,我希望能够Product从ProductInCategory单个 Db 查询中删除整组s 。


控制器方法接收 aproduct_id和 a category_id,而不是 a ProductGroupId。


对于单个Product我一直在使用此查询将其从类别中删除:


ProductInCategory unCategorize = await _context.ProductsInCategories

    .Where(pic => pic.ProductId == product_id && pic.ProductCategoryId == category_id)

    .FirstOrDefaultAsync();

进而:


_context.Remove(unCategorize);

await _context.SaveChangesAsync();

现在,如果我有一个List<Product>要从中删除的ProductsInCategories,查询会是什么样的?


我试过这个,但它在.Any()-bit上失败了:


Product product = await _context.Products

    .Where(p => p.Id == product_id)

    .FirstOrDefaultAsync();


List<Product> products = await _context.Products

    .Where(g => g.ProductGroupId == product.ProductGroupId)

    .ToListAsync();


List<ProductInCategory> unCategorize = await _context.ProductsInCategories

    .Where(pic => pic.ProductId == products.Any(p => p.Id)

        && pic.ProductCategoryId == category_id)

    .ToListAsync();


白衣非少年
浏览 196回答 3
3回答

摇曳的蔷薇

控制器方法接收 aproduct_id和 a category_id,而不是 aProductGroupId第一个问题是为什么该方法product_id在需要对ProductGroupId.这听起来很糟糕的设计,但无论如何,让我们首先将其product_id转换为所需的ProductGroupId(这将花费我们额外的数据库查询):int? productGroupId = await _context.Products&nbsp; &nbsp; .Where(p => p.Id == product_id)&nbsp; &nbsp; .Select(p => (int?)p.ProductGroupId)&nbsp; &nbsp; .FirstOrDefaultAsync();if (productGroupId == null){&nbsp; &nbsp; // Handle non existing product_id&nbsp;}剩下的就是访问 LINQ to Entities 查询中的导航属性,EF Core 会将其转换为生成的 SQL 查询中的适当联接。不需要中间Product列表。List<ProductInCategory> unCategorize = await _context.ProductsInCategories&nbsp; &nbsp; .Where(pic => pic.Product.ProductGroupId == productGroupId)&nbsp; &nbsp; .ToListAsync();

九州编程

我可以建议你想要的代码修复,但有一个更好的解决方案:不加载数据以.在您的代码示例中,您正在从数据库加载数据,然后告诉 EF 删除加载的项目。那效率不高。应该没有理由加载数据,您应该能够简单地执行查询而无需加载数据。据我所知,实体框架不能“有条件删除”(因为没有更好的名字),例如:DELETE FROM People WHERE Name = 'Bob'&nbsp;如果您想根据特定列值(实体的 ID 除外)删除项目,则不能依赖实体框架,除非您想加载数据(这会影响性能)。这里有两个更好的选择:1.自己执行SQL查询context.Database.ExecuteSqlCommand(&nbsp; &nbsp; &nbsp; &nbsp; "DELETE FROM Products WHERE ProductGroupId = " + product.ProductGroupId&nbsp;&nbsp; &nbsp; &nbsp; );&nbsp;这就是我一直这样做的方式。旁注:我期待有关 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 行为(根据我的经验)。
随时随地看视频慕课网APP
我要回答