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返回一个任意选择的行.