2010-11-18 76 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这列必须更新,这是这一行的目的。

相关问题