我有两张桌子:
发票(InvoiceID,InvoiceNumber)
发票_产品(InvoiceID,ProductID,IsFinalized)
我显示所有发票的清单,并且有按钮可以按“已完成”或“未最终确定”的发票进行过滤。最终确定的发票是上的每个产品IsFinalized==true
。
目前我的代码执行速度非常慢:
IEnumerable<Invoice> invoices = db.Invoices;
if (isFinalized) // filter by finalized invoices
{
List<Invoice> unfinalizedInvoices = new List<Invoice>();
foreach (var invoice in invoices)
{
int invoicesProductsCountTotal = db.Invoices_Products.Where(l => l.InvoiceID == invoice.InvoiceID).Count();
int invoicesProductsCountFinalized = db.Invoices_Products.Where(l => l.InvoiceID == invoice.InvoiceID && l.IsFinalized == true).Count();
if (invoicesProductsCountTotal != invoicesProductsCountFinalized)
{
unfinalizedInvoices.Add(invoice);
}
}
invoices = invoices.Except(unfinalizedInvoices);
}
else
{
List<Invoice> finalizedInvoices = new List<Invoice>();
foreach (var invoice in invoices)
{
int invoicesProductsCountTotal = db.Invoices_Products.Where(l => l.InvoiceID == invoice.InvoiceID).Count();
int invoicesProductsCountFinalized = db.Invoices_Products.Where(l => l.InvoiceID == invoice.InvoiceID && l.IsFinalized == true).Count();
if (invoicesProductsCountTotal == invoicesProductsCountFinalized && invoicesProductsCountFinalized > 0)
{
finalizedInvoices.Add(invoice);
}
}
invoices = invoices.Except(finalizedInvoices);
}
我意识到这不是最佳的,但我喜欢传播我的LINQ,以便我能够阅读和理解它。
我的问题:有什么方法可以让我的查询更快使用.All
或.Any
或其他什么,或者我是否需要重新考虑我的数据库设计(可能在发票表中添加一个额外的列)
修改:第三个表是产品(ProductID,ProductNumber),但您知道
答案 0 :(得分:1)
您现在正在加载所有发票,然后为每张发票加载产品。这肯定会很慢(当你开始添加大量发票时它会变慢很多)。
您应该在EntityFramework中创建多对多关系。 (见example)
您的课程将如下所示:
class Invoice
{
List<Product> Products {get; set;}
}
class Product
{
bool IsFinalized {get; set;}
}
现在您可以使用LINQ来确保只执行只获取所需数据的SQL语句:
var invoices = db.Invoices.Where(i => i.Products.All(p => p.IsFinalized == finalized));
答案 1 :(得分:0)
迭代每个Invoice
,然后向数据库发出其他请求将非常缓慢。让您的查询立即获取所有信息,然后迭代结果。
var result = from invoice in db.Invoices
join invoicedProduct in db.Invoices_Products
on invoice.InvoiceId equals invoicedProduct.InvoiceId
select new
{
InvoiceId = invoice.InvoiceId,
ProductId = invoicedProduct.ProductId,
IsFinalized = invoicedProuct.IsFinalized
};
var grpResult = from record in result
group record by record.ProductId into productGrp
select productGrp;
foreach( var grp in grpResult )
{
Console.WriteLine( "ProductId: " + grp.Key.ToString( ) );
Console.WriteLine( "TotalCount: " + grp.Count( ).ToString( ) );
Console.WriteLine( "Finalized: " + grp.Where( item => item.IsFinalized ).Count( ).ToString( ) );
}
答案 2 :(得分:0)
if (isFinalized)
{
invoices = invoices.Where(l => l.Invoices_Products.All(m => m.IsFinalized == true));
}
else
{
List<Invoice> finalizedInvoices = invoices.Where(l => l.Invoices_Products.All(m => m.IsFinalized == true)).ToList();
invoices = invoices.Except(finalizedInvoices);
}
^^这似乎大大改善了性能。哦,谢谢你的聆听