【问题标题】:Entity framework DbContext update value without query and by foreign key实体框架 DbContext 更新值无需查询和外键
【发布时间】:2017-06-16 06:05:43
【问题描述】:

我有一种更新某些表格的方法。对于更新,我需要首先获得TestProcess,但我不喜欢那样。如何在没有select(firstOrDefault)操作的情况下更新TestProcess,仅用于更新操作?

方法示例:

public void UpdateTestProcess(int id, string updateID)
{
    using (TestEntities context = new TestEntities())
                {
                    TestProcess pr = context.TestProcess.FirstOrDefault(x => x.MyID == id);
                    pr.UpdateID = updateID;             

                    context.TestProcess.Attach(pr);
                    context.ObjectStateManager.ChangeObjectState(pr, EntityState.Modified);
                    context.SaveChanges();
               }
}

【问题讨论】:

标签: c# entity-framework-5 updates dbcontext


【解决方案1】:
TestProcess pr = new TestProcess()
{
    MyID == id,
};

context.Set<TestProcess>().Attach(pr);

pr.UpdateID = updateID;

context.SaveChanges();

如果您将值设置为该类型的默认值(例如,将int 设置为0),则不会将其视为更改,您需要手动设置状态。

pr.UpdateID = updateID;
context.Entry(pr).Property(p => p.UpdateID).IsModified = true;

你可以把这些代码放在扩展方法中,这样你就可以做这样的事情(我将把实现留作练习):

Foo entity = this.DbContext.GetEntityForUpdate<Foo>(
    item => item.ID, model.ID
    );

this.DbContext.UpdateProperty(entity, item => item.Name, model.Name);

【讨论】:

  • 如果我使用 ObjectContext 如何实现你的例子?
  • 为什么要在 EF 5 中使用 ObjectContext?
  • 在这种情况下我帮不了你。 DbContext 已经被推荐了一段时间,如果情况允许,你应该使用它。
  • 在您的示例中,MyID 是主键。我不仅需要通过主键进行更新,还需要通过外键进行更新。如果我用你的例子 TestProcess pr = new TestProcess() { ForeignKey = id };和 pr.UpdateID = updateID; context.Entry(pr).Property(p => p.UpdateID).IsModified = true;之后我有错误存储更新、插入或删除语句影响了意外的行数 (0)。自加载实体后,实体可能已被修改或删除。刷新 ObjectStateManager 条目。是否可以通过外键更新?
  • 我不相信 EF 能够在不提供主键的情况下进行这样的更新。
【解决方案2】:

您可以这样做(您可能应该拥有所有测试过程数据):

TestProcess pr = new TestProcess();

pr.Id = id;
pr.UpdateID = updateID;

context.Attach(pr);
context.ObjectStateManager.ChangeObjectState(pr, EntityState.Modified);
context.SaveChanges();

【讨论】:

  • 这是行不通的。我有错误:参数 1:无法从 'Process' 转换为 'System.Data.Objects.DataClasses.IEntityWithKey'
  • 我正在尝试 context.AttachTo("TestProcesses", pr); context.ObjectStateManager.ChangeObjectState(pr, EntityState.Modified); context.TestProcesses.MergeOption = MergeOption.OverwriteChanges; context.AcceptAllChanges();但不保存更改
【解决方案3】:

代码:

TestProcess testprocess = dbcontext.TestProcesses.Attach(new TestProcess { MyID = id });
tp.UpdateID = updateID;
dbcontext.Entry<TestProcess>(testprocess).Property(tp => tp.UpdateID).IsModified = true;
dbcontext.Configuration.ValidateOnSaveEnabled = false;
dbcontext.SaveChanges();

结果 TSQL:

exec sp_executesql N'UPDATE [dbo].[TestProcesses]
SET [UpdateID] = @0
WHERE ([MyID] = @1)
',N'@0 bigint,@1 bigint',@0=2,@1=1

注意:

需要“IsModified = true”行,因为当您创建新的 TestProcess 对象(仅填充了 MyID 属性)时,所有其他属性都有其默认值(0、null 等)。如果你想用“默认值”更新数据库,实体框架将不会检测到更改,然后数据库将不会被更新。

例如:

testprocess.UpdateID = null;

没有“IsModified = true”行将无法工作,因为属性UpdateID,在您创建空TestProcess对象时已经为null,您需要告诉EF该列必须更新,这就是目的这一行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多