2010-11-18 83 views
79

可以說我查詢數據庫並加載項目列表。然後我在詳細視圖窗體中打開其中一個項目,而不是從數據庫中重新查詢項目,而是從列表中的數據源創建項目的一個實例。在沒有先查詢的情況下更新記錄?

有沒有一種方法可以更新數據庫記錄而不需要獲取單個項目的記錄?

這裏有一個例子,我現在怎麼做:

dataItem itemToUpdate = (from t in dataEntity.items 
           where t.id == id 
           select t).FirstOrDefault(); 

然後拉動記錄我更新的項目的一些價值觀和推回錄後:

itemToUpdate.itemstatus = newStatus; 
dataEntity.SaveChanges(); 

我想會有更好的方法來做到這一點,有什麼想法?

+2

這不是一個非常糟糕的方式做事情。你有併發訪問該表嗎? – 2010-11-18 19:15:05

+0

我會認爲這是像EF這樣的ORM在使用中的用法。要允許在應用程序上下文中對要創建/修改/刪除的對象執行操作,而不關心底層數據庫實現? – 2010-11-18 19:24:44

+27

我認爲對於TSQL背景的開發人員來說,試圖接受和接受ORM的方法是有效的,但是查找記錄只是爲了更新它,而不會使用獲取的數據。開發人員不需要關心底層數據庫實現的這個概念就是一個瓶頸。開發人員對整個系統的瞭解越多,解決方案就越好。選項從來都不是一件壞事。 – barrypicker 2011-12-19 20:16:49

回答

61

您應該使用Attach()方法。

Attaching and Detaching Objects

+13

你能舉個例子嗎? – 2012-05-23 15:01:43

+14

context.Products.Attach(product); context.Entry(product).State = EntityState.Modified; – Gabriel 2012-07-15 14:17:24

+4

@Gabriel這不會更新所有的屬性嗎?如果我只想修改一個單詞,該怎麼辦? – 2012-08-15 00:45:55

0

一般來說,如果使用實體框架查詢所有項目,並保存的實體對象,你可以更新實體對象的單個項目,並呼籲SaveChanges()當您完成。例如:

var items = dataEntity.Include("items").items; 
// For each one you want to change: 
items.First(item => item.id == theIdYouWant).itemstatus = newStatus; 
// After all changes: 
dataEntity.SaveChanges(); 

檢索您想要的一個項目不應該生成新的查詢。

+0

有趣的答案,有誰證實了這一點? – Ian 2016-03-21 10:50:22

+3

這與OP的問題完全相同:獲取整個記錄,然後更新它。 .First()將對象反序列化。 – Jerther 2016-04-13 14:21:13

27

您還可以使用數據存儲上下文對數據庫使用直接SQL。示例:

dataEntity.ExecuteStoreCommand 
    ("UPDATE items SET itemstatus = 'some status' WHERE id = 123 "); 

由於性能原因,您可能希望傳遞變量而不是單個硬編碼的SQL字符串。這將允許SQL Server緩存查詢並通過參數重新使用。例如:

dataEntity.ExecuteStoreCommand 
    ("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 }); 

更新 - EF 6.0

dataEntity.Database.ExecuteSqlCommand 
     ("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 }); 
+6

你爲什麼要降級這個答案,而不留下評論。這個建議解決了原作者的問題。 – barrypicker 2012-05-10 21:54:12

+11

ExecuteStoreCommand並不是真正的EF方式,它只是使用'DbContext'中包含的'DbConnection'來執行命令。它不是數據庫不可知的,更不用說持久性不可知了(例如,如果OP切換到XML,這個例子會崩潰)。 – 2013-02-07 20:15:24

+7

@ just.another.programmer - 擁有巨大的權力帶來巨大的責任。 – barrypicker 2013-02-18 00:31:47

6

如果DataItem有場EF將預先驗證(如非空的字段),我們將不得不禁用此背景下,驗證:

DataItem itemToUpdate = new DataItem { Id = id, Itemstatus = newStatus }; 
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true; 
dataEntity.Configuration.ValidateOnSaveEnabled = false; 
dataEntity.SaveChanges(); 
//dataEntity.Configuration.ValidateOnSaveEnabled = true; 

否則我們可以嘗試滿足預驗證並且仍然只更新單個列:

DataItem itemToUpdate = new DataItem 
{ 
    Id = id, 
    Itemstatus = newStatus, 
    NonNullableColumn = "this value is disregarded - the db original will remain" 
}; 
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true; 
dataEntity.SaveChanges(); 

假設dataEntitySystem.Data.Entity.DbContext

您可以驗證次

/*dataEntity.*/Database.Log = m => System.Diagnostics.Debug.Write(m); 
3

的代碼:通過將該給DbContext經產生的E查詢

ExampleEntity exampleEntity = dbcontext.ExampleEntities.Attach(new ExampleEntity { Id = 1 }); 
exampleEntity.ExampleProperty = "abc"; 
dbcontext.Entry<ExampleEntity>(exampleEntity).Property(ee => ee.ExampleProperty).IsModified = true; 
dbcontext.Configuration.ValidateOnSaveEnabled = false; 
dbcontext.SaveChanges(); 

結果TSQL:

exec sp_executesql N'UPDATE [dbo].[ExampleEntities] 
SET [ExampleProperty ] = @0 
WHERE ([Id] = @1) 
',N'@0 nvarchar(32),@1 bigint',@0='abc',@1=1 

注:

的 「IsModified =真」行,因爲當您創建新的ExampleEntity對象時(僅填充了Id屬性)所有其他屬性都有其默認值(0,null等)。如果您想用「默認值」更新數據庫,更改將不會被實體框架檢測到,然後數據庫將不會更新。

在例如:

exampleEntity.ExampleProperty = null; 

無行「IsModified =真」是行不通的,因爲物業ExampleProperty,已經是空當您創建的空ExampleEntity對象,你需要告訴EF這列必須更新,這是這一行的目的。

相關問題