How to use InsertOrReplace in sqlite.net PCL?

橙三吉。 提交于 2019-12-01 03:31:19

I experienced the same issue as you are describing. Try

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;

I just tried above and it works as expected

Kevin Kraemer

If you change the Key to a nullable type (int?) it should work. then SQLite sees null coming in and generates new id when needed.

public class LogEntry
    {
      [PrimaryKey, AutoIncrement]
      public int? Key { get; set;}
      public DateTime Date { get; set; }
    }

The way this works is the source of much confusion but whereas Insert treats zeroed primary keys as a special case when AutoIncrement is set, InsertOrReplace does not.

So with:

[PrimaryKey, AutoIncrement]
public int id { get; set; }

if you InsertOrReplace a series of zero id records into a new table, the first will be stored at id: 0 and each subsequent one will save over it. Whereas if you just Insert each one then because of the AutoIncrement the first will save at id: 1 and the next at id: 2 etc. as you might expect.

If you change the key type to a nullable int, then records with null ids will be treated as inserts by InsertOrReplace, and you don't actually need the AutoIncrement attribute at all in this case, they will still save in sequence starting at 1.

[PrimaryKey]
public int? id { get; set; }

If you can't use that for some reason you can do your own check for zero ids and for those call Insert instead, e.g.

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

but in this case you must use the AutoIncrement attribute, otherwise first zero insert will be saved at 0 and the second will throw a constraint exception when it attempts insert another such.

To get the result you want, you need to make the id property of your class nullable. see here link

My solution for this is kind of similar to Joacar's, but instead of doing an update, I select the item, if it's null, I create a new item, otherwise update that items values, and then call 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);
}

It might not be optimal, but it worked for me.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!