IQueryable <t>给出与List <t>不同的结果

时间:2015-05-18 22:33:06

标签: c# linq entity-framework

如果我在我的实体框架结果上使用Select on IQueryable,我将得到4个项目。

如果我在IQueryable.ToList()上使用Select,我会得到所有36项。

这是函数的代码:

public ImagesGetModelView Get(int start, int count)
{
    if (count <= 0) count = 9;
    else if (count > ImageHandler.MaxResult) count = ImageHandler.MaxResult;    

        IQueryable<Image> imagesList = ImagesHandler.FetchRangeScore(start, count)
           .Where(m => m.Domain == Database.Enums.ImageDomain.Gfycat);

        //Works using list :(
        //var list = imagesList.ToList();

        //Select all subreddits once
        //Returns 4 instead of 36 if not using the list ...
        //Returns 1 instead of 2 with Distinct() if not using the list
        IEnumerable<Subreddit> subreddits = imagesList
           .Select(m => m.Subreddit); //.Distinct();           

        ImagesGetModelView result = new ImagesGetModelView()
        {
            Items = imagesList,
            Subreddits = subreddits
        };

        return result;
    } 

public IQueryable<Image> FetchRangeScore(int a_start, int a_count)
    {
        return Repository.AllQueryable().OrderByDescending(m => m.Score)
          .Skip(a_start).Take(a_count);
    }

36项中的2项Subreddits将是截然不同的。但由于从Select()中只取出了36个中的4个,因此只能找到1个不同的。

所以我可以使用LINQ表达式来获取正确的数据,以便使用distinct语句,或者在继续使用Select&amp; amp;之前我必须将它变成List。不同的功能?

编辑:
通过将where satement从结尾移动到整个查询的开头。 它似乎现在正常工作。选择返回所有36项e.t.c ...这反过来使得Distinct工作,因为它可以找到多于1个唯一值。

 public IQueryable<Image> FetchRangeScore(int a_start, int a_count)
    {
        return Repository.AllQueryable()
          .Where(m => m.Domain == Database.Enums.ImageDomain.Gfycat)
          .OrderByDescending(m => m.Score)
          .Skip(a_start).Take(a_count);
    }

2 个答案:

答案 0 :(得分:5)

如果没有源数据,很难确定,但Distinct在推送​​到SQL时的工作方式不同。

SQL DISTINCT查询将提取所有值不同的记录。当您对内存中的对象列表执行Distinct调用时,默认情况下它将使用 instance 相等。所以你可能会回来&#34;重复&#34;对象(所有字段值相同的对象),但它们将是不同的&#34;实例&#34;,因此Distinct将它们视为不同的对象。

所以这取决于你想要什么 - 你想要所有Subreddit包括重复还是你想要不同的

要回答您的问题 - 如果您不希望将Distinct调用传递给SQL,则可以调用AsEnumerable()而不是ToList,这会使所有进一步的Linq查询Linq-to-Objects(IEnumerable<T>)查询而不是Linq-to- {whatever}(IQueryable<T>)查询,而没有将项目放在列表中的开销。

答案 1 :(得分:5)

最有可能的是,Where子句在SQL Server中的行为与在.NET中的行为不同。具体来说,根据您的归类设置等,各种.Domain值可能只有大小写或类似的差异,使它们与SQL中的Gfycat“相等”,而不是在C#中。

您可以捕获.ToString()上的IQueryable<>以查看正在生成的SQL并自行尝试。

IQueryable<Image> imagesList = ImagesHandler.FetchRangeScore(start, count)
   .Where(m => m.Domain == Database.Enums.ImageDomain.Gfycat);
Debug.WriteLine(imagesList.ToString());