我从这里使用PCL版本的sqlite.net(https://github.com/oysteinkrog/SQLite.Net-PCL)。
这是我的简单课程。
public class LogEntry
{
[PrimaryKey, AutoIncrement]
public int Key { get; set;}
public DateTime Date { get; set; }
}
当创建新的LogEntry实例时,Key会自动设置为0.我将Date设置为something,然后调用InsertOrReplace。记录确实保存在我的数据库中。 Key字段获取自动增量值,该值恰好为0,因为它是第一个记录。
然后我创建一个新的LogEntry实例(Key自动初始化为0)并将日期设置为其他内容。然后我调用InsertOrReplace。由于存在Key为0的现有记录,该记录会更新。
处理这个问题的正确方法是什么?我考虑将Key初始化为-1,但这似乎也没有用。
有没有人有这个工作的例子?
答案 0 :(得分:23)
如果将Key更改为可空类型(int?),它应该可以工作。然后SQLite看到null进来并在需要时生成新的id。
public class LogEntry
{
[PrimaryKey, AutoIncrement]
public int? Key { get; set;}
public DateTime Date { get; set; }
}
答案 1 :(得分:9)
我遇到了与你描述的问题相同的问题。尝试
var rowsAffected = Connection.Update(object);
if(rowsAffected == 0) {
// The item does not exists in the database so lets insert it
rowsAffected = Connection.Insert(object);
}
var success = rowsAffected > 0;
return success;
我刚刚尝试过,它按预期工作
答案 2 :(得分:2)
这种方法的工作原理很混乱,但Insert
将归零主键视为设置AutoIncrement
时的特殊情况,InsertOrReplace
则不然。
所以:
[PrimaryKey, AutoIncrement]
public int id { get; set; }
如果您InsertOrReplace
将一系列零id记录放入新表中,则第一个将存储在id: 0
,后续每个将保存在其中。然而,如果您只是Insert
,那么由于AutoIncrement
,第一个将保存在id: 1
而下一个将保存在id: 2
等等。正如您所期望的那样。
如果您将密钥类型更改为可以为null的int,那么具有空ID的记录将被视为InsertOrReplace
的插入,并且在这种情况下您实际上根本不需要AutoIncrement
属性,他们仍然会从1开始按顺序保存。
[PrimaryKey]
public int? id { get; set; }
如果您出于某种原因无法使用该功能,则可以自行检查是否为零ID,而对于那些请拨打Insert
,例如
Func<Foo, int> myInsertOrReplace = x =>
{
return x.id == 0 ? _db.Insert(x) : _db.InsertOrReplace(x);
};
但是在这种情况下你必须使用AutoIncrement
属性,否则第一个零插入将保存在0,第二个将在尝试插入另一个时抛出一个约束异常。
答案 3 :(得分:1)
要获得所需的结果,您需要使类的id属性可为空。看这里 link
答案 4 :(得分:0)
我的解决方案类似于Joacar,但我没有做更新,而是选择项目,如果它为null,我创建一个新项目,否则更新项目值,然后调用InserOrReplace。
var existingKey = await this.GetItem(key);
Item item;
if (existingKey.Value != null)
{
profile = new Item
{
Id = existingKey.Id,
Key = existingKey.Key,
Value = newValue,
};
this.InsertOrReplaceAsync(item);
}
else
{
item = new Item
{
Key = key,
Value = value,
};
this.InsertAsync(item);
}
它可能不是最佳的,但它对我有用。