【问题标题】:LINQ select distinct c#LINQ选择不同的c#
【发布时间】:2012-07-26 16:14:24
【问题描述】:

我正在尝试执行一个不包含重复的IdUser 值的查询,但不起作用。

这是我的 linq 查询:

var sql= (from u in db.USER
          join c in db.CONSULT on u.IdUser equals c.IdUser 
          select new UsuersViewModel 
                 {  
                    IdUser = c.IdUser, 
                    DateCreate=c.DateCreate, 
                    IdTypeConsult = c.IdTypeConsult, 
                    Sex=u.Sex 
                 })
                 .Distinct();

我想要这个:

SELECT   distinct CONSULT.IdUser , CONSULT.DateCreate, 
         CONSULT.IdTypeConsult , USER.Sex
FROM   CONSULT INNER JOIN
       USER ON CONSULT.IdUser = USER.IdUser 

查询给出重复记录

为什么它不起作用?

【问题讨论】:

  • 你没有给它任何“独特”的东西。 :)
  • 请扩展“不起作用”...它会给您重复吗?它什么都不返回吗?非独特集(在Distinct() 之前)是否包含您所期望的?在不知道问题的情况下很难猜测出了什么问题......
  • 是的,正如@OnlyBolivianHere 所说,在 SQL 语句中,您声明 CONSULT.IdUser 应该是不同的,在您的 LINQ 中,您是在声明每个整条记录都必须是不同的
  • @OnlyBolivianHere:你什么意思?他肯定有一个被区分的 Ienumerable...
  • @stevethethread:这不是 distinct 在 SQL 中的工作方式。它指的是整个记录集(很像select top 10 a, b, c 中的top 10 指的是整个数据集)。

标签: c# linq-to-sql


【解决方案1】:

我认为您想使用Distinct(IEqualityComparer<T>) 重载。你需要创建一个IEqualityComparer 来做你想做的事:

class UserComparer : IEqualityComparer<UsuersViewModel >
{
    public bool Equals(UsuersViewModel  x, UsuersViewModel y)
    {
        //Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        return x.IdUser == y.IdUser;
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.

    public int GetHashCode(UsuersViewModel  user)
    {
        //Check whether the object is null
        if (Object.ReferenceEquals(user, null)) return 0;

        return user.IdUser == null ? 0 : user.IdUser.GetHashCode();
    }
}

然后像这样使用它:

var comparer = new UserComparer();
var sql= (from u in db.USER
          join c in db.CONSULT on u.IdUser equals c.IdUser 
          select new UsuersViewModel 
                 {  
                    IdUser = c.IdUser, 
                    DateCreate=c.DateCreate, 
                    IdTypeConsult = c.IdTypeConsult, 
                    Sex=u.Sex 
                 })
                 .Distinct(comparer);

我不确定这是否会生成您想要的 SQL,但可能会得到您想要的结果。

【讨论】:

  • 编辑了代码;但是,它假定您将用户拼写为用户。如果不是这种情况,请将“用户”替换为“用户”
  • 如果我不知道错误详细信息是什么,我也帮不上什么忙。
  • 请特别注意我对“用户”和“用户”的评论,如果您忽略了,您会收到错误消息。
  • Error 1 Argument 1: cannot convert from 'System.Linq.IQueryable&lt;REPORTMVC3.Models.Usuers&gt;' to ' System.Linq.ParallelQuery&lt;REPORTMVC3.Models.USER&gt;'
  • 请记住,如果您使用 Linq to Entities,这将引发错误,因为结果不是普通的 IEnumerable,而是 IQueryable;所以你需要在 .Distinct(comparer) 之前添加 .AsEnumerable()。
【解决方案2】:

在比较类实例(与匿名类型)时,您需要定义“平等”。对于匿名类型,编译器假定相等意味着“所有字段都相等”,就像 SQL 一样。所以你有几个选择:

  1. 在查询中使用匿名类型,使用.Distinct(),然后转换为强类型,
  2. 定义一个IEqualityComparer&lt;Usuers&gt; 类并将其传递给Distinct
  3. Usuers 中覆盖Equals(和GetHashCode

2) 和 3) 将是非常相似的代码。 2) 更灵活(您可以通过定义不同的类以不同的方式定义相等,而 3) 将在您比较 Uusers insatnces 时使用(不仅在此查询中)。

查看我对类似问题的回答here

【讨论】:

  • 我什至没有注意到原始代码使用的是定义类型而不是匿名类型。这只是我意识到在阅读这篇文章之后第二次重新阅读。很好地发现了这一点。 :)
【解决方案3】:

注意:以下代码可以在 LinqPad 中运行(http://www.linqpad.net/ 免费) - 只需将语言下拉菜单设置为“C# 程序”并将代码粘贴到编辑器窗口中。

您可以使用“组”来提供您的独特要求,如下所示:

void Main()
{
    var db = new DataBase();
    var sql= (from u in db.USER
          join c in db.CONSULT on u.IdUser equals c.IdUser 
          group c by new { c.IdUser, c.DateCreate, c.IdTypeConsult, u.Sex } into gc
          select new UsuersViewModel 
                 {  
                    IdUser = gc.Key.IdUser, 
                    DateCreate=gc.Key.DateCreate, 
                    IdTypeConsult = gc.Key.IdTypeConsult, 
                    Sex=gc.Key.Sex 
                 })
                 .Distinct();
    sql.Dump("SQL Distinct Demo");
}
public class Consultation {
    public int  IdUser {get;set;}
    public DateTime DateCreate {get;set;}
    public int IdTypeConsult {get;set;}
}
public class UsuersViewModel : Consultation {
    public string Sex {get;set;}
}
public class DataBase {
    public IEnumerable<Consultation> CONSULT {
        get { 
            return new List<Consultation>{
                new Consultation { IdUser = 1, DateCreate=DateTime.Today, IdTypeConsult = 2},
                new Consultation { IdUser = 2, DateCreate=DateTime.Today.AddDays(1), IdTypeConsult = 4}
            };
        }}
    public IEnumerable<UsuersViewModel> USER {
        get {
            return new List<UsuersViewModel>{
                new UsuersViewModel { IdUser = 1, Sex="M"},
                new UsuersViewModel { IdUser = 1, Sex="M"},
                new UsuersViewModel { IdUser = 2, Sex="F"},
                new UsuersViewModel { IdUser = 2, Sex="F"}
            };
        }}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 2011-10-16
    相关资源
    最近更新 更多