Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InsertOrReplace ignores PrimaryKey AutoIncrement #327

Open
Johan-dutoit opened this issue Nov 12, 2014 · 19 comments
Open

InsertOrReplace ignores PrimaryKey AutoIncrement #327

Johan-dutoit opened this issue Nov 12, 2014 · 19 comments
Assignees
Labels

Comments

@Johan-dutoit
Copy link

If I use InsertOrReplace to insert a new record, which has a primary key of 0, it inserts the record with 0 instead of using the next available id.

@AndersSoborg
Copy link

Hi There

Please have a look at #312

@Johan-dutoit
Copy link
Author

Hi,

I don't believe they are related. #312 says it always returns 1 where I am not worried about what it is returning, but more on what is happening.

Just had a look at the source code, and yes it is using the Insert method, but the issues are still unrelated.

@aMarCruz
Copy link

Hack the SQLite.cs code. Comment line 1930:

    //   decl += "autoincrement ";

in the class for your tables, declare your primary key as...

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

...after INSERT, because the AutoIncrement attribute, sqlite-net copy the id value to the field Id of the instance, where you can read it.

SQLite 3.8.x automatically generates a new key for fields of type INTEGER PRIMARY KEY (ascending) if the value is not given in the INSERT, no need "AUTOINCREMENT".

With this hack, sqlite-net sends only INTEGER PRIMARY KEY with CREATE TABLE command for fields [PrimaryKey, AutoIncrement].
You need set the "AutoIncrement" attribute, sqlite-net will not update the value of Id w/o this.

(sorry by my "english").

@ColonelDuddits
Copy link
Contributor

If I understand your question correctly, the behavior you describe is a feature of SQLite. SQLite allows you to specify values for the primary key column. Because id is specified as zero the first time, your row gets inserted with zero. Each time you use InsertOrReplace with id = 0 after that, you are actually replacing an existing row. To get the result you want, you need to make the id property of your class nullable. Don't set a value for it; InsertOrReplace will manage that for you.

@MartinWeb
Copy link

Sorry to dig that post but it appears that the problem is still there.
AutoIncrement is apparently not working with Insert.

I didn't find any answer to that on Google or here.
So i did a workaround before i execute the Insert, i check for the last Id of the table and increment it (if one row is present).

Stock lastStock = database.Table<Stock> ().OrderByDescending (u => u.Id).FirstOrDefault ();
if (lastStock != null) {
    newStock.Id = lastStock.Id + 1;
} else {
    lastStock.Id = 1;
}

@tibitoth
Copy link

Yes, the InsertOrReplace is still not working :(
My workaround to solve that problem: Update and Insert method is working good.

using (var dbConn = new SQLiteConnection(_dbPath))
{
    var item = dbConn.Table<DbType>().FirstOrDefault(r => r.Id == id);
    if (item != null)
    {
        item.Property = newValue;
        dbConn.Update(item, typeof(DbType));
    }
    else
    {
        item = new DbType() { Property = newValue, };
        dbConn.Insert(item, typeof(DbType));
    }
}

@ghost
Copy link

ghost commented Apr 9, 2016

Thanks @ColonelDuddits making PK nullable made InsertOrReplace work correctly.

@UweKeim
Copy link

UweKeim commented Oct 18, 2016

Making the ID nullable did work for me too.

I've changed something like this:

[Table(@"Categories")]
public sealed class ShopCategoryModel
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }

    // ...
}

to something like this:

[Table(@"Categories")]
public sealed class ShopCategoryModel
{
    [PrimaryKey, AutoIncrement]
    public int? Id { get; set; }

    // ...
}

But I think it is really "ugly" to use nullable IDs in my code (always using GetValueOrDefault() decreases readability, IMO).

@shujjju
Copy link

shujjju commented Jan 15, 2017

Thanks @ColonelDuddits, @Kwoth making PK nullable worked for me.

@andrewpros
Copy link

Well it is not working as is should, the null id get always incremented by 1, whats the point, it should work like insert or update, if it is the some record, don't update the id.

@praeclarum praeclarum added the Bug label Aug 3, 2017
@praeclarum praeclarum self-assigned this Aug 3, 2017
@praeclarum
Copy link
Owner

This is looking like a bug to me. I'll take a look...

@brminnick
Copy link

I confirmed this bug is still present in v1.6.258-beta.

Following @UweKeim's work-around and using a nullable int, e.g. int?, for the [PrimaryKey] worked for me:

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

@manicsquirrel
Copy link

It's 2021 and this is still a problem and a barrier to new users. I would still be pulling my hair out had I not found this issue. Requiring the use of a nullable integer for an autoincremented primary key violates the concept of a primary key.

@olumide-oyetoke
Copy link

I've resorted to always using nullable int for primary key.

@IndianaGary
Copy link

IndianaGary commented Jun 20, 2021 via email

@dhippo78
Copy link

dhippo78 commented Nov 5, 2021

No need for InsertOrReplace.

Wait for InsertAsync....

var T = DatabaseAsyncConnection.InsertAsync(object);
T.Wait();
return T;

Guaranteed to work.

@justdmitry
Copy link

+1 from me that this bug is very annoying.

InsertOrReplace behave differently with Id=0 compared to Insert: Insert replaces value with autogenerated one, while InsertOrUpdate does not. This is not consistent behavior.

@it11111111
Copy link

+1 from me. Spent a whole day breaking my head to find out this was actually a very annoying bug.

@memsom
Copy link

memsom commented Jan 5, 2023

If I understand your question correctly, the behavior you describe is a feature of SQLite. SQLite allows you to specify values for the primary key column. Because id is specified as zero the first time, your row gets inserted with zero. Each time you use InsertOrReplace with id = 0 after that, you are actually replacing an existing row. To get the result you want, you need to make the id property of your class nullable. Don't set a value for it; InsertOrReplace will manage that for you.

This fixes the issue for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests