实体框架6:插入或更新

时间:2018-04-12 14:18:31

标签: c# entity-framework

我希望在具有Entity Framework的表中插入或更新行,具体取决于表中是否已存在主键(字符串)。

我使用以下代码来执行此操作:Insert or update pattern

private void InsertOrUpdate(ServiceMonitoring sm)
{
    try
    {
        using (var context = new MyDBEntities())
        {
            context.Entry(sm).State = sm.serviceName == null ?
                EntityState.Added :
                EntityState.Modified;
            context.SaveChanges();
        }
        log.Info("ServiceMonitoring updated");
    }
    catch (Exception ex)
    {
        log.Error("Error updating ServiceMonitoring");
        log.Debug(ex.Message);
    }

}

当行(例如serviceName =“MyService”)已经存在时,它正常工作。然后执行更新。但是如果该行不存在,INSERT将失败并收到以下错误消息:

  

存储更新,插入或删除语句会影响意外   行数(0)。自那以后,实体可能已被修改或删除   实体已加载。

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:3)

更新或插入模式与MSDN示例中的主键一起使用的原因是它被标记为Identity字段。将实体添加到DbContext时,EF会将Id字段的默认值设置为0,并且数据库将在执行INSERT时为该行分配唯一值。

您尝试错误地调整“更新或插入”模式以使用属性serviceName,解决方案是使用您引用的MSDN文章提供的模式,或执行查询。 / p>

为了完整,为什么你的改编不起作用? 因为您传入ServiceMonitoring对象并期望context.Entry(sm)在数据库中查询正确的数据行。它不是先生。因此,在您的情况下,EntityState.Added基本上是无法访问的代码。

private void InsertOrUpdate(ServiceMonitoring sm)  
{
    try
    {
        //this brand new DbContext instance has not queried your database, and is not tracking any objects!
        using (var context = new MyDBEntities())  
        {
            //if (sm.serviceName is null) <- should never be null, as it's the ServiceMonitoring object you are passing into the function.
            //The DbContext.Entry() does not know whether or not this actually exists in the database, it only allows you to inform
            //EF about the state of the object.
            context.Entry(sm).State = sm.serviceName == null ?  //<- Always false (unless you *really* want a serviceName to not have a name)
                EntityState.Added : // <- code unreachable
                EntityState.Modified; //This is where the exception occurs, your code is always generating an UPDATE statement.
                                        //When the entry exists in the database, EF's generated UPDATE statement succeeds.
                                        //When the entry does not exist, the UPDATE statement fails.
            context.SaveChanges();
        }
        log.Info("ServiceMonitoring updated");
    }
    catch (Exception ex)
    {
        log.Error("Error updating ServiceMonitoring");
        log.Debug(ex.Message);
    }
}