Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Lambda表达式LINQ等价于同一表/变量上的SQL Exists查询_C#_Sql_Entity Framework_Linq_Lambda - Fatal编程技术网

C# Lambda表达式LINQ等价于同一表/变量上的SQL Exists查询

C# Lambda表达式LINQ等价于同一表/变量上的SQL Exists查询,c#,sql,entity-framework,linq,lambda,C#,Sql,Entity Framework,Linq,Lambda,我正在尝试使用lambda表达式格式在LINQ中复制以下SQL查询(以使其与迄今为止开发的代码保持一致): 在查看了其他问题(这是我能找到的最接近的问题,但没有显示如何“或”条件)之后,我认为下面的内容会起作用,但它只会导致堆栈溢出(严重)异常和一条关于未加载pdb文件的消息,我认为这有点让人费解 products = products .Where(p => !p.DateObsolete.HasValue || p.DateObsolete

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

在查看了其他问题(这是我能找到的最接近的问题,但没有显示如何“或”条件)之后,我认为下面的内容会起作用,但它只会导致堆栈溢出(严重)异常和一条关于未加载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));
产品是可计量的变量

在此上下文中,产品定义为以下数据集:

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的新手(并在上面发布问题),因此我们将非常感谢您的帮助。

您可以通过加入来完成此任务

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();
这将在参考1-3中将产品连接到自身,但随后选择“左侧”项目及其版本、“右侧”版本和批准日期。Where条件隔离了“右侧”版本大于左侧版本且未批准日期的情况。结果将是“左”产品,其对应产品符合这些标准

更新: 如果您已经将产品过滤到一组已知的适用产品,那么这将对对象起作用。例如:

// 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));

正如Aleks Andreev和Ivan Stoev所建议的,将表达式分配给一个新变量可以解决问题。我不确定为什么第一次这样做不起作用,但我猜,在完成查询后,我尝试将结果重新分配回原始变量,以便不必在更改后的所有代码中更改变量名。

我们可以看到产品实体吗?我指的是此查询中隐含的所有属性。缺少信息:EF版本+类型和
产品的原产地。我猜数据库是Sql Server。请尝试将表达式分配给新变量,如
var newProducts=products。其中(…
最有可能与
products
变量闭包相关。尝试
var query=products.Where(…)
而不是将结果查询分配给
products
变量。对不起,@AleksAndreev和Ivan,我又尝试了一次重新分配(我试图跟踪故障的确切点)它起作用了:我不确定我做了什么不同。谢谢,但我不确定我是否可以这样做。更多背景:此查询是在原始产品集合上运行的几个查询之一,用于识别满足用户指定搜索条件的产品集合,因此我需要在products变量rat中对集合运行它她比原始的数据集要好。我尝试了这个,但似乎不能用变量开始连接。如果这只是暴露了我对LINQ的理解不足,那就很抱歉了!
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));