Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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语句中使用.Select和.Where_C#_Linq_Unique_Distinct - Fatal编程技术网

C# 在单个LINQ语句中使用.Select和.Where

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

我需要使用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
        }
    }
}
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; }
    }
}