[英]Unexpected behavior in entity framework
I ran into what I think is a really odd situation with entity framework. 我遇到了我认为实体框架非常奇怪的情况。 Basically, if I update an row directly with a sql command, when I retrive that row through linq it doesn't have the updated information.
基本上,如果我使用sql命令直接更新行,当我通过linq检索该行时,它没有更新的信息。 Please see the below example for more information.
有关更多信息,请参阅以下示例。
First I created a simple DB table 首先,我创建了一个简单的DB表
CREATE TABLE dbo.Foo (
Id int NOT NULL PRIMARY KEY IDENTITY(1,1),
Name varchar(50) NULL
)
Then I created a console application to add an object to the DB, update it with a sql command and then retrieve the object that was just created. 然后我创建了一个控制台应用程序,用于向DB添加对象,使用sql命令更新它,然后检索刚刚创建的对象。 Here it is:
这里是:
public class FooContext : DbContext
{
public FooContext() : base("FooConnectionString")
{
}
public IDbSet<Foo> Foo { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Foo>().ToTable("Foo");
base.OnModelCreating(modelBuilder);
}
}
public class Foo
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class Program
{
static void Main(string[] args)
{
//setup the context
var context = new FooContext();
//add the row
var foo = new Foo()
{
Name = "Before"
};
context.Foo.Add(foo);
context.SaveChanges();
//update the name
context.Database.ExecuteSqlCommand("UPDATE Foo Set Name = 'After' WHERE Id = " + foo.Id);
//get the new foo
var newFoo = context.Foo.FirstOrDefault(x => x.Id == foo.Id);
//I would expect the name to be 'After' but it is 'Before'
Console.WriteLine(string.Format("The new name is: {0}", newFoo.Name));
Console.ReadLine();
}
}
The write line at the bottom prints out "Before" however I would expect that it prints out "After". 底部的写行打印出“之前”,但我希望它打印出“之后”。 The odd thing about it is that if I run profiler I see the sql query run and if I run the query in management studio myself, it returns "After" as the name.
关于它的奇怪之处在于,如果我运行探查器,我会看到sql查询运行,如果我自己在管理工作室中运行查询,则返回“After”作为名称。 I am running sql server 2014.
我正在运行SQL Server 2014。
Can someone please help me understand what is going on here? 有人可以帮我理解这里发生了什么吗?
UPDATE: 更新:
It is going to the database on the FirstOrDefault line. 它将转到FirstOrDefault行的数据库。 Please see the attached screen shot from sql profiler.
请参阅sql profiler附带的屏幕截图。
So my question really is this: 所以我的问题是这样的:
1) If it is caching, shouldn't it not be going to the DB? 1)如果是缓存,不应该不去DB吗? Is this a bug in EF?
这是EF中的一个错误吗?
2) If it is going to the db and spending the resources, shouldn't EF update the object. 2)如果要进入db并花费资源,不应该更新EF对象。
FooContext
includes change tracking and caching, so the in-memory object that is returned from your query is the same instance that you added earlier. FooContext
包括更改跟踪和缓存,因此从查询返回的内存中对象与先前添加的实例相同。 Calling SaveChanges()
does clear the context and FooContext
is not aware of the changes that happened underneath it in the database. 调用
SaveChanges()
确实清除了上下文,并且FooContext
不知道数据库中它下面发生的更改。
This is usually a good thing -- not making expensive database calls for every operation. 这通常是一件好事 - 不会为每个操作进行昂贵的数据库调用。
In your sample, try making the same query from a new FooContext
, and you should see "After". 在您的示例中,尝试从新的
FooContext
进行相同的查询,您应该看到“After”。
Responding to your updated question, yes, you are right. 回答您的更新问题,是的,您是对的。 I missed before that you were using
FirstOrDefault()
. 在你使用
FirstOrDefault()
之前我错过了。 If you were using context.Find(foo.Id)
, as I wrongly assumed, then there would be no query. 如果您正在使用
context.Find(foo.Id)
,正如我错误地假设的那样,那么就没有查询。
As for why the in-memory object is not updated to reflect the change in the database, I'd need to do some research to do anything more than speculate. 至于为什么内存中的对象没有更新以反映数据库中的变化,我需要做一些研究来做更多的事情而不是推测。 That said, here is my speculation:
那就是说,这是我的猜测:
SaveChanges()
is called -- what should happen? SaveChanges()
会怎样? - 会发生什么?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.