Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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#_Performance_Linq - Fatal编程技术网

C# 优化LINQ,而不是创建新集合/循环

C# 优化LINQ,而不是创建新集合/循环,c#,performance,linq,C#,Performance,Linq,我有两张桌子: 发票(发票ID、发票编号) 发票\u产品(发票ID、产品ID、IsFinalized) 我显示了所有发票的列表,并且有按钮可以按“已完成”或“未完成”发票进行过滤。最终确定的发票是指发票上的每个产品都是IsFinalized==true 目前,我有以下代码,执行速度非常慢: IEnumerable<Invoice> invoices = db.Invoices; if (isFinalized) // filter by finalized invoices {

我有两张桌子:

发票(发票ID、发票编号)
发票\u产品(发票ID、产品ID、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);
}
IEnumerable发票=db.发票;
if(isFinalized)//按已定案发票过滤
{
List unfinalizedInvoices=新列表();
foreach(发票中的var发票)
{
int invoicesproductsconttotal=db.Invoices\u Products.Where(l=>l.InvoiceID==invoice.InvoiceID.Count();
int invoicesproductscontfinalized=db.Invoices\u Products.Where(l=>l.InvoiceID==invoice.InvoiceID&&l.IsFinalized==true).Count();
if(发票产品目录总计!=发票产品目录最终化)
{
未完成的发票。添加(发票);
}
}
发票=发票。除(未完成的发票);
}
其他的
{
List=new List();
foreach(发票中的var发票)
{
int invoicesproductsconttotal=db.Invoices\u Products.Where(l=>l.InvoiceID==invoice.InvoiceID.Count();
int invoicesproductscontfinalized=db.Invoices\u Products.Where(l=>l.InvoiceID==invoice.InvoiceID&&l.IsFinalized==true).Count();
如果(InvoicesProductScontTotal==InvoicesProductScontFinalized&&InvoicesProductScontFinalized>0)
{
添加(发票);
}
}
发票=发票。除了(最终确定的发票);
}
我意识到这不是最优的,但我喜欢展开我的LINQ,以便我能够阅读和理解它。
我的问题:是否有任何方法可以使用
。All
。any
或其他什么,或者我是否需要重新考虑我的数据库设计(可能在发票表中添加一个额外的列)


编辑:第三个表是产品(ProductID,ProductNumber),但您知道,

此时您正在加载所有发票,然后加载每个发票的产品。这肯定会很慢(当您开始添加大量发票时,速度会慢得多)

您应该在EntityFramework中创建多对多关系。(见附件)

您的类将如下所示:

class Invoice 
{
    List<Product> Products {get; set;}
}
class Product
{
    bool IsFinalized {get; set;}
}

迭代每个
发票
,然后向数据库发出附加请求将非常缓慢。让您的查询一次获取所有信息,然后迭代结果

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( ) );
}
if(已定稿)
{
发票=发票。其中(l=>l.invoices\u Products.All(m=>m.IsFinalized==true));
}
其他的
{
List finalizedVoices=invoices.Where(l=>l.invoices\u Products.All(m=>m.IsFinalized==true)).ToList();
发票=发票。除了(最终确定的发票);
}

^^这似乎大大提高了性能。哦,谢谢你的收听

谢谢。但我使用
Invoices\u Products
作为多对多链接表-它有一些列,如“数量”、“销售价格”等(顺便说一句,我不是先使用代码-先使用数据库),您仍然可以这样做,但不是多对多,而是定义两个一对多关系。然后,您也可以使用LINQ遍历它,而不是使用
Join
然后紧接着使用
GroupBy
您应该从一开始就使用
GroupJoin
。@Viper,ta了解详情there@Servy这有区别吗?直到
foreach
,才会执行第一条语句。从未使用过
GroupJoin
btw;)@Viper它将大大简化代码;它是否会影响生成的SQL,我不能说;你得试试看。无论怎样,我都不会感到惊讶。
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( ) );
}
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);
}