C# 在单个LINQ语句中使用.Select和.Where
我需要使用LINQ从特定表中收集不同的Id。关键是我还需要一个WHERE语句,它应该只根据我设置的需求过滤结果。对于不得不大量使用LINQ来说,这是比较新的,但我或多或少地使用了以下代码:C# 在单个LINQ语句中使用.Select和.Where,c#,linq,unique,distinct,C#,Linq,Unique,Distinct,我需要使用LINQ从特定表中收集不同的Id。关键是我还需要一个WHERE语句,它应该只根据我设置的需求过滤结果。对于不得不大量使用LINQ来说,这是比较新的,但我或多或少地使用了以下代码: private void WriteStuff(SqlHelper db, EmployeeHelper emp) { String checkFieldChange; AnIList tableClass = new AnIList(db, (int)emp.PersonId); v
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
}
}
}
private void WriteStuff(SqlHelper db,EmployeeHelper emp)
{
字符串检查字段更改;
AnIList tableClass=新AnIList(db,(int)emp.PersonId);
var linq=tableClass.Items
.在哪里(
x=>x.UserId==emp.UserId
&&x.日期>更改前的日期
&&x.日期<日期后生效
&& (
(x.Field==插入)
||(x.Field==已删除)))
)
).OrderByDescending(x=>x.Id);
if(linq!=null)
{
foreach(linq中的TableClassChanges项)
{
AnotherList payTxn=新的AnotherList(db,item.Id);
checkFieldChange=GetChangeType(item.FieldName);
//从每个项目检索数据的其他代码
//并将其写入文本文件
}
}
}
我试图为var linq添加.Distinct,但它仍然返回重复的项(意味着具有相同的Id)。我已经浏览了很多网站,并尝试在查询中添加.Select,但是.Where子句出现了中断。在其他一些文章中,查询检索值并将其放入变量的方式有所不同。我也尝试使用.GroupBy,但当使用Id作为键时,我得到了“至少一个对象必须实现IComparable”
查询实际上是有效的,我能够按照我所需要的规范从列中输出数据,但我似乎无法进行.Distinct工作(这是唯一真正缺少的东西)。我尝试创建两个var,其中一个触发一个不同的调用,然后使用嵌套的foreach来确保值是唯一的,但是将数千条记录收集起来对性能的影响太大了
我也不确定是否需要重写或使用IEnumerable来满足我的需求,我想我应该四处询问这个问题,以防有更简单的方法,或者是否可以同时使用这两种方法。选择和。在哪里只在一个语句中工作?为了适合您的类型,您可以实现IEquatable
,并为Equals
和GetHashCode
提供合适的定义,否则它将使用默认实现:比较引用等式(假设您使用的是引用类型)
从手册中:
Distinct(IEnumerable)方法返回不包含重复值的无序序列。它使用默认的相等比较器default来比较值
默认相等比较器default用于比较实现IEquatable泛型接口的类型的值。要比较自定义数据类型,需要实现此接口,并为该类型提供自己的GetHashCode和Equals方法
在您的情况下,看起来您可能只需要比较ID,但您也可能需要比较其他字段,这取决于两个对象“相同”对您意味着什么
您也可以考虑使用./p>
请注意,这只是LINQ到对象,但我假设您正在使用它
另一种选择是将GroupBy
和First
相结合:
var query = // your query here...
.GroupBy(x => x.Id)
.Select(g => g.First());
例如,这也适用于LINQ to SQL。是否将
IEqualityComparer
传递给.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();
}
}
您是在
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()
,但这是可选的:)因为您试图比较两个不同的对象,所以需要首先实现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; }
}
}
类程序
{
静态void Main(字符串[]参数)
{
List testData=新列表()
{
新测试(1,“测试”),
新测试(2,“测试”),
新测试(2,“测试”)
};
var result=testData.Where(x=>x.Id>1).Distinct(new MyComparer());
}
}
公共类MyComparer:IEqualityComparer
{
公共布尔等于(测试x,测试y)
{
返回x.Id==y.Id;
}
公共int GetHashCode(测试对象)
{
返回string.Format(“{0}{1}”,obj.Id,obj.Name).GetHashCode();
}
}
公开课考试
{
公共测试(int-id,字符串名)
{
this.id=id;
this.name=名称;
}
私有int-id;
公共整数Id
{
获取{return id;}
设置{id=value;}
}
私有字符串名称;
公共字符串名
{
获取{返回名称;}
设置{name=value;}
}
}
我希望这会有所帮助。您的问题似乎暗示表中有多行具有相同的id,但数据不同——这并不完全符合逻辑。请澄清你的数据看起来像什么,以及ID到底是怎么回事。嗨,乔恩,这实际上是正确的。此处的Id是一个事务Id,并跟踪在单个命令中已更改为特定用户的所有内容(即,通过此事务Id编辑字段a、b和c)。我需要区分它,因为唯一需要的数据是更新到该特定用户的最新行,所以无论在单个事务中是否有多个编辑,只需要最新的更改
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; }
}
}