簡體   English   中英

在單個 LINQ 語句中使用 .Select 和 .Where

[英]Using .Select and .Where in a single LINQ statement

我需要使用 LINQ 從特定表中收集不同的 Id。 問題是我還需要一個 WHERE 語句,該語句應該僅根據我設置的要求過濾結果。 不得不如此頻繁地使用 LINQ 相對較新,但我或多或少地使用了以下代碼:

private void WriteStuff(SqlHelper db, EmployeeHelper emp)
{
    String checkFieldChange;
    AnIList tableClass = new AnIList(db, (int)emp.PersonId);
    var linq = tableClass.Items
        .Where(
           x => x.UserId == emp.UserId 
             && x.Date > DateBeforeChanges 
             && x.Date < DateAfterEffective 
             && (
                     (x.Field == Inserted)
                  || (x.Field == Deleted)))
                )
             ).OrderByDescending(x => x.Id);

    if (linq != null)
    {
        foreach (TableClassChanges item in linq)
        {
            AnotherIList payTxn = new AnotherIList(db, item.Id);
            checkFieldChange = GetChangeType(item.FieldName);

            // Other codes that will retrieve data from each item 
            // and write it into a text file
        }
    }
}

我試圖為 var linq 添加 .Distinct 但它仍然返回重復的項目(意味着具有相同的 Id)。 我已經閱讀了很多網站,並嘗試在查詢中添加一個 .Select,但 .Where 子句卻中斷了。 還有其他文章,其中查詢與檢索值並將其放入 var 的方式有些不同。 我也嘗試使用 .GroupBy 但在使用 Id 作為鍵時我得到一個“至少一個對象必須實現 IComparable”。

該查詢實際上有效,我能夠從具有我需要的規范的列中輸出數據,但我似乎無法使 .Distinct 工作(這是唯一真正缺少的東西)。 我試圖創建兩個變量,其中一個觸發一個不同的調用,然后有一個嵌套的 foreach 以確保這些值是唯一的,但是成千上萬的記錄來收集性能影響是否太多了。

我也不確定是否必須覆蓋或使用 IEnumerable 來滿足我的要求,並認為我會問這個問題以防萬一有更簡單的方法,或者是否可以同時使用 .Select 和 .Where 工作在一個聲明中?

您是在Where()還是之前添加了Select()

由於並發邏輯,您應該在后面添加它:

 1 Take the entire table  
 2 Filter it accordingly  
 3 Select only the ID's  
 4 Make them distinct.  

如果您先執行 Select,則 Where 子句只能包含 ID 屬性,因為所有其他屬性都已被編輯掉。

更新:為清楚起見,此運算符順序應該有效:

db.Items.Where(x=> x.userid == user_ID).Select(x=>x.Id).Distinct();

可能想在最后添加一個.toList()但這是可選的:)

為了讓Enumerable.Distinct適用於您的類型,您可以實現IEquatable<T>並為EqualsGetHashCode提供合適的定義,否則它將使用默認實現:比較引用相等(假設您使用的是引用類型) .

從手冊:

Distinct(IEnumerable) 方法返回一個不包含重復值的無序序列。 它使用默認的相等比較器 Default 來比較值。

默認相等比較器 Default 用於比較實現 IEquatable 泛型接口的類型的值。 要比較自定義數據類型,您需要實現此接口並為該類型提供您自己的 GetHashCode 和 Equals 方法。

在您的情況下,您可能只需要比較 ID,但您可能還想比較其他字段,這取決於兩個對象“相同”對您意味着什么。

您也可以考慮使用morelinq 中的DistinctBy

請注意,這只是 LINQ to Objects,但我認為這就是您正在使用的。

另一種選擇是結合GroupByFirst

 var query = // your query here...
    .GroupBy(x => x.Id)
    .Select(g => g.First());

例如,這也適用於 LINQ to SQL。

由於您要比較兩個不同的對象,因此您首先需要實現 IEqualityComparer 接口。 下面是一個簡單的控制台應用程序的示例代碼,它使用了 IEqualityComparer 的不同且簡單的實現:

 class Program
{
    static void Main(string[] args)
    {
        List<Test> testData = new List<Test>()
        {
            new Test(1,"Test"),
            new Test(2, "Test"),
            new Test(2, "Test")
        };

        var result = testData.Where(x => x.Id > 1).Distinct(new MyComparer());
    }
}

public class MyComparer : IEqualityComparer<Test>
{
    public bool Equals(Test x, Test y)
    {
        return x.Id == y.Id;
    }

    public int GetHashCode(Test obj)
    {
        return string.Format("{0}{1}", obj.Id, obj.Name).GetHashCode();
    }
}


public class Test
{
    public Test(int id, string name)
    {
        this.id = id;
        this.name = name;
    }

    private int id;

    public int Id
    {
        get { return id; }
        set { id = value; }
    }
    private string name;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}

我希望這有幫助。

您是否將IEqualityComparer<T>傳遞給.Distinct()

像這樣的東西:

internal abstract class BaseComparer<T> : IEqualityComparer<T> {
    public bool Equals(T x, T y) {
        return GetHashCode(x) == GetHashCode(y);
    }

    public abstract int GetHashCode(T obj);
}

internal class DetailComparer : BaseComparer<StyleFeatureItem> {
    public override int GetHashCode(MyClass obj) {
        return obj.ID.GetHashCode();
    }
}

用法:

list.Distinct(new DetailComparer())

您可以像這樣使用 LINQ 輕松查詢

考慮這個 JSON

{
    "items": [
        {
            "id": "10",
            "name": "one"
        },
        {
            "id": "12",
            "name": "two"
        }
    ]
}

像這樣把它放在一個名為json的變量中,

JObject json = JObject.Parse("{'items':[{'id':'10','name':'one'},{'id':'12','name':'two'}]}");

您可以使用以下 LINQ 查詢從名稱為"one"的項目中選擇所有 ID

var Ids =
    from item in json["items"]
    where (string)item["name"] == "one"
    select item["id"];

然后,您將在 IEnumerable 列表中得到結果

暫無
暫無

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

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