代码之家  ›  专栏  ›  技术社区  ›  Ted

servicestack:update生成“duplicate entry”

  •  0
  • Ted  · 技术社区  · 6 年前

    我试过阅读文档,但我不明白为什么更新方法会产生“重复条目”mysql错误。

    医生说

    在其最简单的形式中,更新没有任何过滤器的任何模型都将更新每个字段,但用于将更新筛选到此特定记录的ID除外:

    所以我尝试一下,然后传入一个对象,如下所示。ID为2的行已经存在。

    使用(var _db=_dbfactory.open())
    {
    客户coreObject=新客户(…);
    coreObject.id=2;
    coreObject.objectname=“更改的值”;
    _ db.update<customer>(coreObject);//<--错误“重复条目”
    }
    

    是的,有使用.save等选项,但.update中缺少什么?在我阅读它时,它应该使用它的id属性来更新数据库中的行,而不是插入新行?

    .

    所以我尝试一下,然后传入一个对象,如下所示。ID为2的行已存在。

    using (var _db = _dbFactory.Open())
    {
        Customer coreObject = new Customer(...);
        coreObject.Id = 2;
        coreObject.ObjectName = "a changed value";
        _db.Update<Customer>(coreObject); // <-- error "duplicate entry"
    }
    

    是的,有使用.save等选项,但.update中缺少什么?在我阅读它时,它应该使用它的id属性来更新数据库中的行,而不是插入新行?

    1 回复  |  直到 6 年前
        1
  •  2
  •   mythz    6 年前

    这个方法的问题是您正在更新一个通用对象 T 但是你的更新API说要更新具体的 Customer 类型:

    public void MyTestMethod<T>(T coreObject) where T : CoreObject
    {
        long id = 0;
        using (var _db = _dbFactory.Open())
        {
            id = _db.Insert<T>(coreObject, selectIdentity: true);
    
            if (DateTime.Now.Ticks == 0)
            {
                coreObject.Id = (uint)id;
                _db.Delete(coreObject);
            }
            if (DateTime.Now.Ticks == 0)
            {
                _db.DeleteById<Customer>(id);
            }
            if (DateTime.Now.Ticks == 0)
            {
                coreObject.Id = (uint)id;
                coreObject.ObjectName = "a changed value";
                _db.Update<Customer>(coreObject);
            }
        }           
    }
    

    其中ormlite假定您使用不同的/匿名对象来更新customer表,类似于:

    db.Update<Customer>(new { Id = id, ObjectName = "a changed value", ... });
    

    因为它没有WHERE筛选器,所以它将尝试用相同的主键更新所有行。

    相反,您希望更新相同的实体,或者传入泛型类型 T 或者通过不传递任何类型来推断,例如:

    _db.Update<T>(coreObject);
    _db.Update(coreObject);
    

    它将使用Ormlite的行为通过更新每个字段来更新实体,但主键除外,它在 WHERE 将更新限制为仅更新该实体的表达式。

    v5.1.1中的新行为

    为了防止意外的误用,我在 this commit 它将在使用匿名对象更新实体时使用主键作为筛选器,因此以前的用法是:

    _db.Update<Customer>(coreObject);
    

    将主键添加到Where筛选器,而不是将其包含在集合列表中。此更改可从v5.1.1版获得,现在 available on MyGet .