簡體   English   中英

實體框架中出現意外行為

[英]Unexpected behavior in entity framework

我遇到了我認為實體框架非常奇怪的情況。 基本上,如果我使用sql命令直接更新行,當我通過linq檢索該行時,它沒有更新的信息。 有關更多信息,請參閱以下示例。

首先,我創建了一個簡單的DB表

CREATE TABLE dbo.Foo (
    Id int NOT NULL PRIMARY KEY IDENTITY(1,1),
    Name varchar(50) NULL
) 

然后我創建了一個控制台應用程序,用於向DB添加對象,使用sql命令更新它,然后檢索剛剛創建的對象。 這里是:

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();

    }

}

底部的寫行打印出“之前”,但我希望它打印出“之后”。 關於它的奇怪之處在於,如果我運行探查器,我會看到sql查詢運行,如果我自己在管理工作室中運行查詢,則返回“After”作為名稱。 我正在運行SQL Server 2014。

有人可以幫我理解這里發生了什么嗎?

更新:

它將轉到FirstOrDefault行的數據庫。 請參閱sql profiler附帶的屏幕截圖。

在此輸入圖像描述

所以我的問題是這樣的:

1)如果是緩存,不應該不去DB嗎? 這是EF中的一個錯誤嗎?

2)如果要進入db並花費資源,不應該更新EF對象。

FooContext包括更改跟蹤和緩存,因此從查詢返回的內存中對象與先前添加的實例相同。 調用SaveChanges()確實清除了上下文,並且FooContext不知道數據庫中它下面發生的更改。

這通常是一件好事 - 不會為每個操作進行昂貴的數據庫調用。

在您的示例中,嘗試從新的FooContext進行相同的查詢,您應該看到“After”。

更新

回答您的更新問題,是的,您是對的。 在你使用FirstOrDefault()之前我錯過了。 如果您正在使用context.Find(foo.Id) ,正如我錯誤地假設的那樣,那么就沒有查詢。

至於為什么內存中的對象沒有更新以反映數據庫中的變化,我需要做一些研究來做更多的事情而不是推測。 那就是說,這是我的猜測:

  • 數據庫上下文的實例不能返回同一實體的多個實例。 在一個工作單元內,我們必須能夠依賴上下文來返回實體的同一個實例。 否則,我們可能會按不同的標准進行查詢,並獲得表示同一概念實體的3個對象。 那時,上下文如何處理其中任何一個的變化? 如果名稱在其中兩個上更改為不同的值然后調用SaveChanges()會怎樣? - 會發生什么?
  • 鑒於那時上下文最多跟蹤每個實體的單個實例,為什么EF只能在執行查詢時更新該實體? 如果存在未決的內存中更改,EF甚至可以丟棄該更改,因為它知道這些更改。
    • 我認為答案的一部分是在大型實體和大型結果集中區分所有列是性能過高的。
    • 我認為答案的一個重要部分是它執行一個簡單的SELECT語句不應該有可能在整個系統中引起副作用。 實體可以通過某個屬性的值進行分組或循環,並在不確定的時間更改該屬性的值,並且由於SELECT查詢非常不健全。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM