gpt4 book ai didi

c# - Lambda 表达式 LINQ 等同于 SQL Exists Query on Same Table/Variable

转载 作者:行者123 更新时间:2023-11-30 12:55:12 25 4
gpt4 key购买 nike

我正在尝试使用 lambda 表达式格式在 LINQ 中复制以下 SQL 查询(以使其与目前开发的代码保持一致):

SELECT *
FROM Product p
WHERE p.DateObsolete IS NULL
OR p.DateObsolete > GETDATE()
OR EXISTS (
SELECT NULL
FROM dbo.Product p1
WHERE p1.Ref01 = p.Ref01
AND p1.Ref02 = p.Ref02
AND p1.Ref03 = p.Ref03
AND p1.Version = p.Version + 1
AND p1.DateApproved IS NULL
)

在 SO 和其他地方查看了其他问题(Linq subquery same table using lambda 是我能找到的最接近的问题,但没有显示如何“或”条件)我认为以下内容可行,但它只会导致堆栈溢出(严重) 异常和有关未加载 pdb 文件的消息,我认为这是一个转移注意力的问题。

products = products
.Where(p => !p.DateObsolete.HasValue
|| p.DateObsolete > DateTime.Now
|| products.Any(p1 => p1.Ref01 == p.Ref01
&& p1.Ref02 == p.Ref02
&& p1.Ref03 == p.Ref03
&& p1.Version == p.Version + 1
&& p1.DateApproved == null));

products 是一个 IQueryable 变量。

产品在此上下文中定义为 DbSet of:

public class Product
{
public int ProductID { get; set; }

[MaxLength(200)]
public string Name { get; set; }

[MaxLength(3)]
public string Ref01 { get; set; }

[MaxLength(3)]
public string Ref02 { get; set; }

public int Ref03 { get; set; }

public int Version { get; set; }
public DateTime? DateReceivedByGraphics { get; set; }
public DateTime? DateApproved { get; set; }
public DateTime? DateObsolete { get; set; }

public bool Deleted { get; set; }
public bool Discontinued { get; set; }

}

正如您可能了解到的那样,我是 LINQ 的新手(以及在 SO 上发布问题),因此我们将不胜感激地收到任何帮助。

最佳答案

您可以通过加入来完成此操作。

DateTime date = DateTime.Today; // or .Now
var products = context.Products.Join(context.Products,
p1 => new { p1.Ref01, p1.Ref02, p1.Ref03 },
p2 => new { p2.Ref01, p2.Ref02, p2.Ref03 },
(p1, p2) => new { Product = p1, p1.Version, JoinedVersion = p2.Version, JoinedDateApproved = p2.DateApproved } )
.Where(x=> x.Product.DateObsolete > date && x.JoinedVersion == x.Version+1 && !x.JoinedDateApproved.HasValue)
.Select(x=>x.Product)
.ToList();

这会将 Product 与 Ref 1-3 上的自身连接起来,但随后会选择“左侧”项目及其版本、“右侧”版本和批准日期。 Where 条件隔离了“右”版本比左版本大 1 并且没有批准日期的情况。结果将是具有符合这些条件的对应物的“左”产品。

更新:如果您已经将产品筛选为一组已知的适用产品,那么这将适用于对象。例如:

// given products is an IQueryable representing the filtered products...
DateTime date = DateTime.Today; // or .Now

var productList = products.ToList(); // Materialize the EF Queryable into list of entities.

productList = productList.Join(productList,
p1 => new { p1.Ref01, p1.Ref02, p1.Ref03 },
p2 => new { p2.Ref01, p2.Ref02, p2.Ref03 },
(p1, p2) => new { Product = p1, p1.Version, JoinedVersion = p2.Version, JoinedDateApproved = p2.DateApproved } )
.Where(x=> x.Product.DateObsolete > date && x.JoinedVersion == x.Version+1 && !x.JoinedDateApproved.HasValue)
.Select(x=>x.Product)
.ToList();

如果您的目标是尝试将其作为一个 IQueryable 范围限定为 EF,那么我怀疑如果可能的话,它可能不值得复杂性/时间。最坏的情况是,如果您确实想保留 IQueryable,请使用上面的方法将产品 ID 选择到列表中,然后将该列表应用为针对 IQueryable 的过滤器。

var productList = products.ToList(); // Materialize the EF Queryable into list of entities.

// Fetch a list of applicable product IDs.
var productIds = productList.Join(productList,
p1 => new { p1.Ref01, p1.Ref02, p1.Ref03 },
p2 => new { p2.Ref01, p2.Ref02, p2.Ref03 },
(p1, p2) => new { ProductId = p1.ProductId, DateObsolete = p1.DateObsolete, p1.Version, JoinedVersion = p2.Version, JoinedDateApproved = p2.DateApproved } )
.Where(x=> x.DateObsolete > date && x.JoinedVersion == x.Version+1 && !x.JoinedDateApproved.HasValue)
.Select(x=>x.ProductId)
.ToList();

// Filter the original IQueryable.
products = products.Where(x => productIds.Contains(x.ProductId));

关于c# - Lambda 表达式 LINQ 等同于 SQL Exists Query on Same Table/Variable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50873229/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com