如何在sqlite.net PCL中使用InsertOrReplace?

时间:2014-08-20 16:27:00

标签: xamarin sqlite.net

我从这里使用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,但这似乎也没有用。

有没有人有这个工作的例子?

5 个答案:

答案 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);
}

它可能不是最佳的,但它对我有用。