Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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# 如何对对象集合和每个对象内部的集合运行LINQ查询_C#_Linq - Fatal编程技术网

C# 如何对对象集合和每个对象内部的集合运行LINQ查询

C# 如何对对象集合和每个对象内部的集合运行LINQ查询,c#,linq,C#,Linq,我有一个对象集合,其中每个对象也有一个集合。像这样: public class Product { public int Id { get; set; } public List<Tuple<string, double>> Sales { get; set; } } 是否可以在一行中完成此操作?这里的关键是,在实际定义完整个查询之前,不要通过使用SingleOrDefault来具体化查询。改为使用Where,然后在最后使用SingleOrDefault

我有一个对象集合,其中每个对象也有一个集合。像这样:

public class Product
{
    public int Id { get; set; }
    public List<Tuple<string, double>> Sales { get; set; }
}

是否可以在一行中完成此操作?

这里的关键是,在实际定义完整个查询之前,不要通过使用
SingleOrDefault来具体化查询。改为使用
Where
,然后在最后使用
SingleOrDefault

var query = (from product in Model.Products
                where product.Id == someProductId
                let sale = product.Sales.SingleOrDefault(i => i.Item1 == sale.Id)
                where sale != null
                select new
                {
                    product,
                    saleAmount = sale.Item2,
                })
            .SingleOrDefault();
有可能在一行中完成吗

我相信,通过将支票合并到第二个销售数组(如

var products = Model.Products.Where(p => p.Id == product.Id
                                              &&
                                         p.Sales.Any(i => i.Item1 == sale.Id) );

var saleAmount = (products != null && products.Any()) 
                                   ? products.First().Sales.First().Item2.ToString()
                                   : string.Empty;
使用默认值 此解决方案使用默认的人造产品的帮助,该人造产品是预先创建的
产品
,在找不到时使用。在扩展方法中使用它,该方法确定是否已返回空投影,在这种情况下,它将返回faux实例。之后,我们可以安全地提取一个值,该值将是
string.empty
,并将其分配给最后一个字符串
productSale

下面我使用硬编码的
1.5
作为销售价格,以便于阅读示例

// Our default will set saleAmount to string.Empty if nothing is found in Products.
var defProduct = new Product() 
                      { Id    = -1, 
                        Sales = new List<Tuple<string, double>>()
                                  { new Tuple<string,double>(string.Empty, 0.0) }};

var productSale =

Products.Where(p => p.Id == product.Id && p.Sales.Any (s => s.Item2 == 1.5 ) )
        .DefaultIfEmpty( defProduct )
        .First ()
        .Sales.First()
        .Item1;

您将面临
NullReferenceExceptions
,我怀疑您的代码是否会更清晰。我希望您意识到,
SingleOrDefault
如果列表中有多个项具有生成id,将引发异常。您确定不想在此处使用
FirstOrDefault
。@JimMischel,鉴于他正在处理主键,它们不应该被复制。如果它们真的存在,那将是数据中的一个bug,应该抛出。@Servy如果它们是主键,那么(此处nickpicking)
FirstOrDefault
在性能方面更快(因为不需要检查是否有重复项来抛出异常)。@Servy:我没有看到任何说明他正在使用主键的内容。但是如果是这样的话,那当然,这是一个非常有趣的方法。这是否可能使用lambda表达式?@ShaiCohen这是使用lambda表达式。@ShaiCohen A
lambda
表达式是一个条件表达式,它通过“goes to”
=>
语法推断特定的检查语法。您正在思考的
lambda
linq
表达式,它可以是Servy所做的查询语法(从技术上讲,他是一个混合体),也可以是我在示例中使用的方法语法。我们都使用
lambda
s来表示检查操作,例如
i=>i.Item1==sale.Id
。有关更多信息,请参阅。@OmegaMan:谢谢您的澄清。就在你认为你知道一些事情的时候@我们都去过那里。很乐意帮忙。
// Our default will set saleAmount to string.Empty if nothing is found in Products.
var defProduct = new Product() 
                      { Id    = -1, 
                        Sales = new List<Tuple<string, double>>()
                                  { new Tuple<string,double>(string.Empty, 0.0) }};

var productSale =

Products.Where(p => p.Id == product.Id && p.Sales.Any (s => s.Item2 == 1.5 ) )
        .DefaultIfEmpty( defProduct )
        .First ()
        .Sales.First()
        .Item1;
void Main()
{

    var targetSalePrice = 1.5;
    var targetProductId = 2;

    var Products = new List<Product>() { new Product()
                                           { Id = 2,
                                             Sales = new List<Tuple<string, double>>()
                                            { new Tuple<string,double>("actual", 1.6) } }
                                        };


// Our default will set saleAmount to string.Empty if nothing is found in Products.
var defProduct = new Product() { Id = -1, Sales = new List<Tuple<string, double>>()
                                  { new Tuple<string,double>("faux string.Empty", 0.0) }};

var productSale =

Products.Where(p => p.Id == targetProductId 
                   && p.Sales.Any (s => s.Item2 == targetSalePrice ) )
        .DefaultIfEmpty( defProduct )
        .First ()
        .Sales.First ()
        .Item1;

    productSale.Dump(); // outputs the string "faux string.Empty" from the faux default.

}

// Define other methods and classes here


public class Product
{
    public int Id { get; set; }
    public List<Tuple<string, double>> Sales { get; set; }
}