使用First()获取LINQ结果的第二项?

Soo*_*ony 1 c# linq entity-framework

我是Linq和EntityFramework的新手.这是我在学习时遇到的示例程序.

表中的数据如下:

BlogId  Title
1       Hello Blog
2       New Blog
3       New Blog
Run Code Online (Sandbox Code Playgroud)

我有以下Linq代码,试图读取第一个博客ID(预计为2):

var name = "New Blog";
var blogs = (from b in db.Blogs
                where b.Title == name
                orderby b.Title
                select b);//.ToList();

Console.Write("The first id: ");
Console.WriteLine(blogs.First().BlogId);
Run Code Online (Sandbox Code Playgroud)

结果是3.

然后我使用ToList():

var blogs = (from b in db.Blogs
                where b.Title == name
                orderby b.Title
                select b).ToList();
Console.Write("The first id: ");
Console.WriteLine(blogs.First().BlogId);
Run Code Online (Sandbox Code Playgroud)

结果是2.

任何人都可以帮忙解释一下吗?或者这是一个错误?

谢谢.

//////////////////////// 更新 ///////////////////////// ////

我刚刚删除了数据库中的数据并插入了一些新项目.现在表格是这样的:

BlogId  Title
5       New Blog
6       New Blog
7       New Blog
8       New Blog
Run Code Online (Sandbox Code Playgroud)

然后我运行上面的程序(不带ToList()),First()方法返回id 6 所以我假设方法总是返回上面情况中的第二项.它似乎与RDBMS没有任何关系.谁能解释一下?

谢谢.

////////////////////////////////////////////////// ///

仅供参考,以下是整个.cs文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data.Entity;
using System.ComponentModel.DataAnnotations;

namespace SampleNew
{
    class Program
    {
        public class Blog
        {
            [Key]
            public Int32 BlogId { get; set; }
            public String Title { get; set; }
            public virtual List<Post> Posts { get; set; } 
        }

        public class Post
        {
            [Key]
            public Int32 PostId { get; set; }
            public String Title{ get; set; }

            public String Content { get; set; }
        }

        public class BlogContext : DbContext
        {
            public DbSet<Blog> Blogs{ get; set; }

            public DbSet<Post> Posts { get; set; }
        }

        static void Main(string[] args)
        {
            using (var db = new BlogContext())
            {
                // Create and save a new Blog 
                // Console.Write("Enter a name for a new Blog: ");
                var name = "New Blog";

                //var blog = new Blog { Title = name };
                var blogs = (from b in db.Blogs
                             where b.Title == name
                             orderby b.Title
                             select b).ToList();

                Console.Write("The first id: ");
                Console.WriteLine(blogs.First().BlogId);

                Console.WriteLine(blogs.Count());

                Blog blog = null;
                foreach (Blog b in blogs)
                {
                    blog = b;
                    Console.WriteLine(blog.BlogId);
                }
                Console.WriteLine(blog.BlogId);

                Console.WriteLine(blogs.First().BlogId);
                Console.WriteLine(blogs.First().BlogId);

                Console.WriteLine(blogs.Last().BlogId);
                Console.WriteLine(blogs.Last().BlogId);


                blog.Posts = new List<Post>();
                var post = new Post { Content = "Test Content2", Title = "Test Title2"};
                blog.Posts.Add(post);

                db.Posts.Add(post);
                db.SaveChanges();

                // Display all Blogs from the database 
                var query = from b in db.Blogs
                            orderby b.Title
                            select b;

                Console.WriteLine("All blogs in the database:");
                foreach (var item in query)
                {
                    Console.WriteLine(item.Title);
                }

                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            } 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

das*_*ght 10

你有两个相同的标题,但有不同的ID.您的RDBMS可以灵活地返回与您'New Blog'希望的任何顺序对应的行,因为您的代码没有指定超出标题要求的任何内容.而且,每次运行相同的查询时,甚至不需要以相同的顺序返回结果.

如果您希望获得可预测的结果,请在LINQ语句中添加"then by"以强制执行您希望的顺序:

var query = from b in db.Blogs
    orderby b.Title, b.BlogId
    select b;
Run Code Online (Sandbox Code Playgroud)

编辑:

当我运行上面的程序时,该First()方法返回id,6所以我假设该方法总是返回上面情况中的第二项.它似乎与RDBMS没有任何关系.谁能解释一下?

这也发生在RDBMS中,并且在没有LINQ的情况下可以重现.这是一个小型演示(链接到sqlfiddle):

create table blogs(blogid int,title varchar(20));
insert into blogs(blogid,title) values (5,'New blog');
insert into blogs(blogid,title) values (6,'New blog');
insert into blogs(blogid,title) values (7,'New blog');
insert into blogs(blogid,title) values (8,'New blog');
SELECT * FROM Blogs ORDER BY Title
Run Code Online (Sandbox Code Playgroud)

此查询以"自然"顺序生成结果:

BLOGID  TITLE
------  --------
5       New blog
6       New blog
7       New blog
8       New blog
Run Code Online (Sandbox Code Playgroud)

但是,此查询是EF运行以获取First()RDBMS中的项目的查询

SELECT TOP 1 * FROM Blogs ORDER BY Title
Run Code Online (Sandbox Code Playgroud)

以自然顺序返回第二行:

BLOGID  TITLE
------  --------
6       New blog
Run Code Online (Sandbox Code Playgroud)

这并不意味着它将返回其他RDBMS中的同一行(链接到MySQL为同一查询返回不同行的演示),甚至在同一个RDBMS中.它只是演示LINQ依赖于RDBMS来选择行,而RDBMS返回一个任意选择的行.