我尝试阅读文档,但是我不明白为什么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属性更新数据库中的行,而不是插入新行?
答案 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
表达式中用来限制更新以仅更新该实体的主键之外。
为防止此类意外滥用,我在this commit中添加了Update API重载,当使用匿名对象更新实体时,它将使用主键作为过滤器,因此您以前的用法是
_db.Update<Customer>(coreObject);
将主键添加到WHERE筛选器,而不是将其包括在SET列表中。从v5.1.1(现在为available on MyGet)开始可以进行此更改。