ServiceStack:Update <t>(...)产生“重复条目”

时间:2018-06-26 21:00:29

标签: servicestack

我尝试阅读文档,但是我不明白为什么Update方法会产生“重复条目” MySql错误。

医生说

  

以最简单的形式,不使用任何过滤器更新任何模型都会更新每个字段,但用于将更新过滤到该特定记录的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属性更新数据库中的行,而不是插入新行?

enter image description here

1 个答案:

答案 0 :(得分:2)

此方法的问题在于,您正在更新通用对象T,但是您的Update 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假定您使用其他/匿名对象来更新客户表,类似于:

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中添加了Update API重载,当使用匿名对象更新实体时,它将使用主键作为过滤器,因此您以前的用法是

_db.Update<Customer>(coreObject);

将主键添加到WHERE筛选器,而不是将其包括在SET列表中。从v5.1.1(现在为available on MyGet)开始可以进行此更改。