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

dak*_*ojo 11 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; }
    }
Run Code Online (Sandbox Code Playgroud)

创建LogEntry的新实例时,Key会自动设置为0.我将Date设置为something,然后调用InsertOrReplace.记录确实保存在我的数据库中.Key字段获取自动增量值,该值恰好为0,因为它是第一个记录.

然后我创建一个新的LogEntry实例(Key自动初始化为0)并将日期设置为其他内容.然后我调用InsertOrReplace.由于存在Key为0的现有记录,因此记录得到更新.

处理这个问题的正确方法是什么?我考虑将Key初始化为-1,但这似乎也没有用.

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

小智 24

如果将Key更改为可空类型(int?),它应该可以工作.然后SQLite看到null进来并在需要时生成新的id.

public class LogEntry
    {
      [PrimaryKey, AutoIncrement]
      public int? Key { get; set;}
      public DateTime Date { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

  • 一个更好的答案可以是这个. (2认同)

joa*_*car 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;
Run Code Online (Sandbox Code Playgroud)

我刚刚尝试过,它按预期工作


sto*_*roz 5

这种工作方式是造成很多混乱的根源,但是Insert将置零的主键视为AutoIncrement设置时的特殊情况,InsertOrReplace则不会。

所以用:

[PrimaryKey, AutoIncrement]
public int id { get; set; }
Run Code Online (Sandbox Code Playgroud)

如果您InsertOrReplace将一系列零 id 记录放入一个新表中,则第一个将存储在id: 0,随后的每个记录都将保存在它上面。而如果您只是Insert每个人,那么因为AutoIncrement第一个将保存 atid: 1和下一个 atid: 2等等,正如您所期望的那样。

如果您将键类型更改为可为空的 int,则具有空 id 的记录将被视为插入 by InsertOrReplace,并且AutoIncrement在这种情况下您实际上根本不需要该属性,它们仍然会从 1 开始按顺序保存。

[PrimaryKey]
public int? id { get; set; }
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因你不能使用它,你可以自己检查零 ids 和那些调用Insert,例如

Func<Foo, int> myInsertOrReplace = x => 
{ 
   return x.id == 0 ? _db.Insert(x) : _db.InsertOrReplace(x); 
};
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,您必须使用该AutoIncrement属性,否则第一个零插入将保存在 0 处,第二个在尝试插入另一个此类时将引发约束异常。