让我说我查询数据库并加载项目列表。然后我打开详细视图表单中的一个项目,而不是从数据库中重新查询该项目,我从列表中的数据源创建项目的实例。
有没有办法可以更新数据库记录而无需获取单个项目的记录?
以下是我现在如何做的示例:
dataItem itemToUpdate = (from t in dataEntity.items
where t.id == id
select t).FirstOrDefault();
然后在拉动记录后,我更新了项目中的一些值并推回记录:
itemToUpdate.itemstatus = newStatus;
dataEntity.SaveChanges();
我认为有更好的方法可以做到这一点,任何想法?
答案 0 :(得分:67)
答案 1 :(得分:32)
您还可以使用数据存储区的上下文对数据库使用直接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 });
答案 2 :(得分:7)
如果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();
假设dataEntity
是System.Data.Entity.DbContext
您可以通过将此添加到DbContext
:
/*dataEntity.*/Database.Log = m => System.Diagnostics.Debug.Write(m);
答案 3 :(得分:7)
代码:
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
注意:
&#34; IsModified = true&#34;因为当您创建新的ExampleEntity对象(仅填充了Id属性)时,所有其他属性都具有其默认值(0,null等),因此需要使用line。如果要使用&#34;默认值&#34;更新数据库,实体框架将不会检测到更改,然后数据库将不会更新。
例如:
exampleEntity.ExampleProperty = null;
如果没有行&#34; IsModified = true&#34; 将无法工作,因为属性ExampleProperty在创建空的ExampleEntity对象时已经为空,您需要向EF说这个列必须更新,并且这就是这条线的目的。
答案 4 :(得分:2)
答案 5 :(得分:0)
一般来说,如果您使用Entity Framework查询所有项目,并且保存了实体对象,则可以更新实体对象中的各个项目,并在完成后调用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();
检索所需的一个项目不应生成新的查询。
答案 6 :(得分:0)
它在EF Core中的工作方式有些不同:
在EF Core中可能有一种更快的方法,但是以下内容可确保无需执行SELECT即可进行UPDATE(在.NET Framework 4.6.2上经过EF Core 2和JET的测试):
确保您的模型没有IsRequired属性
然后使用以下模板(在VB.NET中):
Using dbContext = new MyContext()
Dim bewegung = dbContext.MyTable.Attach(New MyTable())
bewegung.Entity.myKey = someKey
bewegung.Entity.myOtherField = "1"
dbContext.Entry(bewegung.Entity).State = EntityState.Modified
dbContext.Update(bewegung.Entity)
Dim BewegungenDescription = (From tp In dbContext.Model.GetEntityTypes() Where tp.ClrType.Name = "MyTable" Select tp).First()
For Each p In (From prop In BewegungenDescription.GetProperties() Select prop)
Dim pp = dbContext.Entry(bewegung.Entity).Property(p.Name)
pp.IsModified = False
Next
dbContext.Entry(bewegung.Entity).Property(Function(row) row.myOtherField).IsModified = True
dbContext.SaveChanges()
End Using
答案 7 :(得分:0)
我建议使用 Entity Framework Plus
如果您需要使用相同的表达式更新数百或数千个实体,则使用 Entity Framework Core 进行更新可能会非常缓慢。实体在更新之前先加载到上下文中,这对性能非常不利,然后它们一个一个地更新,这使得更新操作更加糟糕。
EF+ 批量更新在单个数据库往返中使用表达式更新多行,无需在上下文中加载实体。
// using Z.EntityFramework.Plus; // Don't forget to include this.
// UPDATE all users inactive for 2 years
var date = DateTime.Now.AddYears(-2);
ctx.Users.Where(x => x.LastLoginDate < date)
.Update(x => new User() { IsSoftDeleted = 1 });