使用 LINQ 从产品列表中删除旧项目
Delete Old Items from Product List Using LINQ
我们有一个 Suppliers
class 和一个 Products
class。我们希望在供应商发布新产品目录时使用 Entity Framework Core 来更新我们的数据库。简化的 classes:
public class Supplier
{
public Guid SupplierId { get; set; }
public List<Product> Products { get; } = new List<Product>();
}
public class Product
{
public string ItemCode { get; set; }
public decimal ItemCost { get; set; }
public Guid SupplierId { get; set; }
public Supplier Supplier { get; set; }
}
我们希望先删除新目录中不在旧目录中的项目。我们尝试使用此 LINQ 查询找到那些项目
List<Product> discontinued = db.Products
.Where(e => !newCatalog
.Any(nc => (e.ItemCode == nc.ItemCode && e.SupplierId == nc.SupplierId))
.ToList();
然后我们删除使用
db.Products.RemoveRange(discontinued);
然而查询 returns 所有产品 Products.SupplierId != newCatalog.SupplierId
。这将删除其他供应商的所有产品。
我们如何制定 LINQ 查询,以便我们只删除 newCatalog
中停产的项目?
正确的条件是
Where(e => e.SupplierId == supplierId && !newCatalog.Any(nc => nc.ItemCode == e.ItemCode))
这需要了解通过产品的SupplierId
。可以用这样的东西提前提取:
var supplierId = newCatalog.Select(e => e.SupplierId).Distinct().Single();
这里的Select
+Distinct
+Single
只是为了保证所有通过的产品都一样SupplierId
。如果您不需要这样的强制执行,您可以简单地从第一个产品中获取它:
var supplierId = newCatalog[0].SupplierId;
在这两种情况下,最好提取它并将其放入查询之外的变量中。
另一个改进可能是用基于 Contains
的条件替换最有可能导致客户评估的 newCatalog.Any(nc => nc.ItemCode == e.ItemCode)
条件,希望转换为 SQL IN (...)
并在服务器。为此,您可以再次将新项目代码提取到查询外的新变量中:
var newItemCodes = newCatalog.Select(nc => nc.ItemCode);
那么查询中的最终条件将是:
Where(e => e.SupplierId == supplierId && !newItemCodes.Contains(e.ItemCode))
我们有一个 Suppliers
class 和一个 Products
class。我们希望在供应商发布新产品目录时使用 Entity Framework Core 来更新我们的数据库。简化的 classes:
public class Supplier
{
public Guid SupplierId { get; set; }
public List<Product> Products { get; } = new List<Product>();
}
public class Product
{
public string ItemCode { get; set; }
public decimal ItemCost { get; set; }
public Guid SupplierId { get; set; }
public Supplier Supplier { get; set; }
}
我们希望先删除新目录中不在旧目录中的项目。我们尝试使用此 LINQ 查询找到那些项目
List<Product> discontinued = db.Products
.Where(e => !newCatalog
.Any(nc => (e.ItemCode == nc.ItemCode && e.SupplierId == nc.SupplierId))
.ToList();
然后我们删除使用
db.Products.RemoveRange(discontinued);
然而查询 returns 所有产品 Products.SupplierId != newCatalog.SupplierId
。这将删除其他供应商的所有产品。
我们如何制定 LINQ 查询,以便我们只删除 newCatalog
中停产的项目?
正确的条件是
Where(e => e.SupplierId == supplierId && !newCatalog.Any(nc => nc.ItemCode == e.ItemCode))
这需要了解通过产品的SupplierId
。可以用这样的东西提前提取:
var supplierId = newCatalog.Select(e => e.SupplierId).Distinct().Single();
这里的Select
+Distinct
+Single
只是为了保证所有通过的产品都一样SupplierId
。如果您不需要这样的强制执行,您可以简单地从第一个产品中获取它:
var supplierId = newCatalog[0].SupplierId;
在这两种情况下,最好提取它并将其放入查询之外的变量中。
另一个改进可能是用基于 Contains
的条件替换最有可能导致客户评估的 newCatalog.Any(nc => nc.ItemCode == e.ItemCode)
条件,希望转换为 SQL IN (...)
并在服务器。为此,您可以再次将新项目代码提取到查询外的新变量中:
var newItemCodes = newCatalog.Select(nc => nc.ItemCode);
那么查询中的最终条件将是:
Where(e => e.SupplierId == supplierId && !newItemCodes.Contains(e.ItemCode))