问题
I have recently moved both of my projects over to SQLite.net-pcl. I have ran into a number of problems so far and this is my latest. Everytime I run my app on iOS it crashes at some point and says SQLite.SQLiteException: Constraint. Android is running on the same PCL and will work first time around but afterwards gives me SQLite.SQLiteException: Constraint until I delete my application storage. Not sure what else to try here.
Code example:-
Object
using System;
namespace App.LocalObjects
{
[Preserve(AllMembers = true)]
public class LocalArticle
{
[SQLite.PrimaryKey, SQLite.Column("articleObjectId")]
public string objectId { get; set; }
public DateTime createdAt { get; set; }
public DateTime updatedAt { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Url { get; set; }
public int Status { get; set; }
public LocalArticle()
{
this.objectId = " ";
this.Title = " ";
this.Description = " ";
this.Url = " ";
}
}
}
Database
using System;
using System.Linq;
using System.Collections.Generic;
using SQLite;
using App.LocalObjects;
namespace App.DataLayer
{
public class Database
{
static object locker = new object();
public SQLiteConnection database;
public string path;
public Database(SQLiteConnection conn)
{
database = conn;
database.CreateTable<LocalArticle>();
}
public int SaveLocalArticleItem(LocalArticle item)
{
lock (locker)
{
LocalArticle article = database.Table<LocalArticle>().FirstOrDefault(x => x.objectId == item.objectId);
if (article != null && article.objectId.Equals(item.objectId) && !article.updatedAt.Equals(item.updatedAt))
{
database.Update(item);
return item.ID;
} else {
return database.Insert(item);
}
}
}
Code to initialize DB:
using System;
using System.IO;
using Android.App;
using App.BusinessLayer.Managers;
using App.BusinessLayer.ParseObjects;
using App.Utils;
using Android.Content;
using Com.Nostra13.Universalimageloader.Core;
using Com.Nostra13.Universalimageloader.Core.Assist;
using Android.Graphics;
using Com.Nostra13.Universalimageloader.Cache.Memory.Impl;
using Com.OneSignal;
using Parse;
using SQLite;
namespace App.Droid
{
[Application(LargeHeap = true)]
public class App : Application
{
public static App Current { get; private set; }
public ModelManager modelManager { get; set; }
private SQLiteConnection conn;
private ImageLoader imageLoader;
public App(IntPtr handle, global::Android.Runtime.JniHandleOwnership transfer)
: base(handle, transfer)
{
Current = this;
}
public override void OnCreate()
{
base.OnCreate();
SetupParse();
SetupDB();
}
private void SetupParse()
{
ParseObject.RegisterSubclass<ParseArticle>();
ParseClient.Initialize(new ParseClient.Configuration
{
ApplicationId = Constants.ParseApplicationID,
Server = Constants.ParseServer
});
}
private void SetupDB()
{
var sqliteFilename = Constants.DBName;
string libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var path = System.IO.Path.Combine(libraryPath, sqliteFilename);
conn = new SQLiteConnection(path);
modelManager = new ModelManager(conn);
}
Here's what my project is currently referencing:-
回答1:
Okay so I have found some information on why this was happening...
So SQLiteException: Constraint is related to if you have a UNIQUE, NOT NULL, or CHECK constraint on a table and you try to do an UPDATE or INSERT. Read more here SQLite Contraints
So my problem was that I have my Primary Key (Which will always be unique), and incorrect code that was checking an item in the database, and instead of updating it, it was trying to insert it. Due to the primary key being the same it was throwing an error. This has now been solved.
回答2:
The first time you run the Android program, there is no database. Therefore, an empty database is created and the INSERT into database with objectId as the PrimaryKey works fine. The second attempt to INSERT an entry into the database with the same objectId key produces this exception.
The solution is to either set AutoIncrement attribute for the objectId:
[SQLite.PrimaryKey, SQLite.AutoIncrement, SQLite.Column("articleObjectId")]
public string objectId { get; set; }
Or be cautious about objectId key of the entries that you want to insert. You can update an existing entry, but you cannot INSERT a new entry with an existing key.
来源:https://stackoverflow.com/questions/41793700/xamarin-sqlite-sqliteexception-constraint-using-sqlite-net-pcl