簡體   English   中英

復雜的LINQ'Any'查詢

[英]Complex LINQ 'Any' query

我有以下與實體框架對應的表:

發票(InvoiceID,InvoiceNumber,IsPaid)
零件(PartID,PartNumber,OrganizationID,IsActive)
發票_零件(發票ID,零件ID,數量,已聲明)

我正在嘗試從Invoices_Parts表中獲取具有多種條件的InvoiceID List 我遇到的問題是“其中Invoices_Parts中的任何 Part均處於活動狀態”。

到目前為止的代碼:

IQueryable<int> partIds = db.Parts.Where(x => 
    x.OrganisationID == loggedInUser.OrganisationID).Select(y => y.PartID);
    // && x.IsActive

List<string> invoiceIds = db.Invoices_Parts.Where(x => 
    !x.IsClaimed && x.Invoice.IsPaid && partIds.Contains(x.PartID)
    .DistinctBy(y => y.InvoiceID)
    .Select(z => z.InvoiceID.ToString()).ToList();

我已經注釋掉了“ && x.IsActive”,因為我希望InvoiceID的列表必須至少滿足IsActive條件的一部分-我不想過濾掉IsActive為false的所有部分。 我如何在LINQ中實現此目標而又無需手動遍歷集合和添加/刪除項?

注意 :如果有人想知道,我將以下幫助方法用於DistinctBy

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    HashSet<TKey> seenKeys = new HashSet<TKey>();
    foreach (TSource element in source)
    {
        if (seenKeys.Add(keySelector(element)))
        {
            yield return element;
        }
    }
}

編輯 :我對每個實體具有以下屬性:

發票:

public virtual ICollection<Invoices_Parts> Invoices_Parts { get; set; }

部分:

public virtual ICollection<Invoices_Parts> Invoices_Parts { get; set; }

Invoices_Parts:

public virtual Invoice Invoice { get; set; }
public virtual Part Part { get; set; }

人們經常使LINQ查詢變得過於復雜,因為它們習慣於從SQL表,聯接等方面進行思考。 通常,如果您用朴素的英語表達您的實際需求,則可以提出一個更簡單的查詢,該查詢的內容幾乎完全相同。

我想要一張發票ID列表,該發票ID來自該發票上任何部分處於活動狀態的已付款發票,等等。

這個怎么樣:

from invoice in db.Invoices
where invoice.IsPaid
where invoice.Invoices_Parts.Any(ip => !ip.IsClaimed && 
    ip.Part.IsActive && 
    ip.OrganisationID == loggedInUser.OrganisationID)
select invoice.InvoiceId

或者,如果您更喜歡方法語法:

db.Invoices.Where(i => i.IsPaid)
.Where(i => i.Invoices_Parts.Any(ip => !ip.IsClaimed && 
    ip.Part.IsActive && 
    ip.OrganisationID == loggedInUser.OrganisationID)
.Select(i => i.InvoiceId)
.ToList();

PS-如果願意,可以執行.ToString() ,但以我的經驗,最好將ID設置為強類型。

PPS-您可以創建一個DistinctBy方法,該方法可以很好地與Entity Framework配合使用(不強制過早評估),如下所示:

public static IQueryable<TSource> DistinctBy<TSource, TKey>(this IQueryable<TSource> source, Excpression<Func<TSource, TKey>> keySelector) {
    return source.GroupBy(keySelector).Select(i => i.FirstOrDefault());
}

好的,假設您希望所有發票中至少有一部分處於活動狀態,那么我將這樣做:

IQueryable<int> partIds = db.Parts
  .Where(x => x.OrganisationID == loggedInUser.OrganisationID && x.IsActive)
  .Select(y => y.PartID);


List<string> invoiceIds = db.Invoices_Parts
   .Where(x =>  !x.IsClaimed && x.Invoice.IsPaid && partIds.Contains(x.PartID))
   .Select(y => y.InvoiceID.ToString())
   .Distinct()
   .ToList();

如果那看起來很像您所擁有的,那是因為。 據我了解的問題,您的存在率已經達到99.99%。

您在這里可以做的是將發票與零件合並,以為每個發票創建所有零件的集合。 一旦有了該集合,確定其中是否有任何活動就很容易了:

List<string> invoiceIds = 
    (from invoice in db.Invoices_Parts
    where !invoice.IsClaimed && invoice.Invoice.IsPaid
    join part in partIds
    on invoice.PartId equals part into parts
    where parts.Any(part => part.IsActive)
    select invoice.InvoiceID)
    .Distinct()
    .ToList();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM