man*_*gia 12 c# entity-framework-core
我对使用 EF Core 还不太熟悉。据我了解,EF Core 有一个“更改跟踪器”,它会查看数据以查看哪些列已被修改,并构建一个仅更新已修改列的 SQL UPDATE 语句,如此处的答案中所述:
然而,这不是我所看到的。例如,我有这个实体:
public class Book
{
public int BookId { get; set; }
[StringLength(255)]
public string Title { get; set; }
public int AuthorId { get; set; }
public Author Author { get; set; }
[StringLength(500)]
public string Description { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后我使用以下代码更新现有行:
class Program
{
static void Main(string[] args)
{
var context = new TestContext();
var book = context.Books.Find(1);
book.Title += " x";
context.Books.Update(book);
context.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
我启动了 SQL Profiler 并运行了这段代码。我期望看到一个只更新“标题”列的 UPDATE 语句,但它总是更新每一列:
exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Books] SET [AuthorId] = @p0, [Description] = @p1, [Title] = @p2
WHERE [BookId] = @p3;
SELECT @@ROWCOUNT;
',N'@p3 int,@p0 int,@p1 nvarchar(500),@p2 nvarchar(255)',@p3=1,@p0=1,@p1=N'',@p2=N'Some Title x'
Run Code Online (Sandbox Code Playgroud)
例如,Description 列未更改,但它位于 UPDATE 语句中,AuthorId 也是如此。
这是为什么?SET 子句中不应该只包含 Title 吗?
Ger*_*old 19
据我了解,EF Core 有一个“更改跟踪器”
这是正确的,这就是为什么一旦实体附加到上下文,您就可以免于将它们标记为已更新。上线后...
book.Title += " x";
Run Code Online (Sandbox Code Playgroud)
...EF 检测到此更改并将标记标记Title为已修改。无需调用该Update方法。
这就是所谓的“连接”场景。
该Update方法适用于断网场景。此时实体对象未附加到上下文,但其值应保存到数据库中,例如在 Web API 后端中。其基本形式是:
public void SaveBook(Book book)
{
// Here, 'book' is the book with the changed Title.
using(var context = new TestContext())
{
context.Books.Update(book);
context.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
现在,EF 无法检测到更改,因为book在进入方法时已经被修改了。你必须告诉 EF 这本书必须更新。但 EF 不知道修改了什么;它能做的最好的事情就是将所有属性(主键除外)标记为已修改。
但是,仍然可以通过将断开连接场景切换为连接场景,使 EF 仅更新实际更新的属性:
public void SaveBook(Book book)
{
// Here, 'book' is the book with the changed Title.
using(var context = new TestContext())
{
var dbBook = context.Books.Find(book.ID);
// Copy book's property values to dbBook.
context.Entry(dbBook).CurrentValues.SetValues(book);
context.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
可能有充分的理由选择后一种方法而不是前一种方法。
| 归档时间: |
|
| 查看次数: |
8357 次 |
| 最近记录: |