[英]LINQ query to get all data about object which is collection of objects when each item of collection has own collection
[英]How to run a LINQ query on a collection of objects and a collection inside of each object
我有一個對象集合,其中每個對象也都有一個集合。 像這樣:
public class Product
{
public int Id { get; set; }
public List<Tuple<string, double>> Sales { get; set; }
}
我想運行LINQ查詢來檢查Product實體是否存在,如果確實存在,則檢查它的Sales集合以查看是否還存在特定的字符串值(來自Tuple)。 如果是這樣,我想返回相應的double(也從Tuple中)。
我知道我可以用幾行代碼來做到這一點,就像這樣:
saleAmount = String.Empty;
product = Model.Products.SingleOrDefault(p => p.Id == product.Id);
if(product != null)
{
productSale = product.Sales.SingleOrDefault(i => i.Item1 == sale.Id);
if(productSale != null)
{
saleAmount = productSale.Item2.ToString();
}
}
可以一行完成此操作嗎?
關鍵是要在定義完整體之后才真正通過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;
此解決方案使用默認的人造預創建Product
的幫助,如果找不到該Product
,則使用該Product
。 在擴展方法DefaultIfEmpty中使用它,該方法確定是否已返回空投影,在這種情況下,它將代替返回人造實例。 之后,我們可以安全地提取一個值為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;
productSale
是string.Empty,如果找不到值或具有要使用的實際值。
LinqPad中的整個測試項目,使用1.5模擬失敗。 使用1.6表示成功。
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; }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.