我需要使用LINQ从特定的表中收集Distinct 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工作(这是唯一真正缺少的)。我尝试创建两个vars,其中一个触发一个不同的调用,然后有一个嵌套的foreach以确保值只是唯一的,但是收集性能影响的数千条记录太多了。
我不确定是否必须覆盖或使用IEnumerable以满足我的要求,并且我认为我会问这个问题,以防万一有更简单的方法,或者是否可以同时使用这两种方法。选择和。只是在一个声明中工作?
答案 0 :(得分:35)
您是否在Select()
之后或之前添加了Where()
?
由于并发逻辑,您应该在之后添加它:
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()
,但这是可选的:)
答案 1 :(得分:11)
为了让Enumerable.Distinct
适用于您的类型,您可以实施IEquatable<T>
并为Equals
和GetHashCode
提供合适的定义,否则它将使用默认实现:比较参考相等性(假设您使用的是引用类型)。
从手册:
Distinct(IEnumerable)方法返回一个不包含重复值的无序序列。它使用默认的相等比较器Default来比较值。
默认的相等比较器Default用于比较实现IEquatable泛型接口的类型的值。要比较自定义数据类型,您需要实现此接口并为该类型提供自己的GetHashCode和Equals方法。
在您的情况下,您可能只需要比较ID,但您可能还想比较其他字段,具体取决于两个对象的含义是什么&#34;相同&#34;。< / p>
您还可以考虑使用DistinctBy
中的morelinq。
请注意,这只是LINQ to Objects,但我认为你正在使用它。
另一个选择是合并GroupBy
和First
:
var query = // your query here...
.GroupBy(x => x.Id)
.Select(g => g.First());
例如,这也适用于LINQ to SQL。
答案 2 :(得分:1)
您是否已将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())
答案 3 :(得分:1)
由于您要尝试比较两个不同的对象,因此首先需要实现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; }
}
}
我希望有所帮助。
答案 4 :(得分:-1)
您可以像这样使用 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 列表中获得结果