Fonctions SQLite personnalisées dans Xamarin.iOS

Je travaille sur la fonction personnalisée de Sqlite sur Xamarin.iOS. J'ai obtenu une réponse d'ici: Afficher les marqueurs sur la carte dans un rayon donné (Xamarin.Android) mais je suis en train de tomber

Tentative de méthode de compilation JIT '(wrapper native-to-managed) Mono.Data.Sqlite.SqliteFunction: ScalarCallback (intptr, int, intptr)' lors de l'exécution avec –aot-only.

Après avoir cherché sur la stack j'ai trouvé que voici une solution: les fonctions personnalisées SQLite avec Mono mais la solution mentionne qu'il est difficile pour moi de comprendre.

Je ne suis pas sûr comment annoter la méthode avec MonoPInvokeCallbackAtsortingbute et la rendre statique parce que la méthode dans la class SqliteFunction est surchargée donc, ne peut pas la rendre statique. Ce serait génial si quelqu'un pouvait m'aider à comprendre cette solution ou fournir des étapes manquantes sur cette solution.

J'utilise le populaire sqlite-net (par Frank A. Krueger) et il utilise à son tour SQLitePCLRaw.bundle_green et SQLitePCL.raw (tous deux par Eric Sink).

Ainsi, vous pouvez utiliser l'API SQLitePCLRaw.ugly pour configurer et accéder facilement aux UDF SQLite.

Une fonction définie par l'user SQLite ( UDF ) Xamarin.iOS sur Xamarin.iOS :

 delegate void SQLiteCallback(sqlite3_context ctx, object user_data, sqlite3_value[] args); [MonoPInvokeCallback(typeof(SQLiteCallback))] static void UDFDistanceFunction(sqlite3_context ctx, object user_data, sqlite3_value[] args) { double radius = 6367; var lat1 = raw.sqlite3_value_double(args[0]); var lng1 = raw.sqlite3_value_double(args[1]); var lat2 = raw.sqlite3_value_double(args[2]); var lng2 = raw.sqlite3_value_double(args[3]); var result = radius * 2 * Math.Asin(Math.Min(1, Math.Sqrt((Math.Pow(Math.Sin((lat2 * (Math.PI / 180) - lat1 * (Math.PI / 180)) / 2.0), 2.0) + Math.Cos(lat1 * (Math.PI / 180)) * Math.Cos(lat2 * (Math.PI / 180)) * Math.Pow(Math.Sin((lng2 * (Math.PI / 180) - lng1 * (Math.PI / 180)) / 2.0), 2.0))))); raw.sqlite3_result_double(ctx, result); } 

Usage:

Utiliser sqlite-net-pcl pour installer des tables, charger / mettre à jour des données, …..

 SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); var dbName = Path.Combine(Path.GetTempPath(), "StackOverflow.db"); var db = new SQLiteConnection(dbName, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create, true); db.CreateTable<BarLocations>(); db.Insert(new BarLocations() { name = "FOOBAR", lat = 47.60357, lng = -122.3295 }); 

Utilisation de SQLitePCLRaw.ugly pour créer et interroger w / SQLDF UDF

 SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3()); var dbName = Path.Combine(Path.GetTempPath(), "StackOverflow.db"); using (sqlite3 dbRaw = ugly.open(dbName)) { dbRaw.create_function("distance", 4, null, UDFDistanceFunction); double currentLatitude = 47.0; double currentLongitude = -122.0; var sql = $"SELECT * FROM barlocations WHERE distance('{currentLatitude.ToSsortingng()}', '{currentLongitude.ToSsortingng()}', barlocations.lat, barlocations.lng) <= 100 ;"; var locs = dbRaw.query<BarLocations>(sql); foreach (var loc in locs) { Console.WriteLine(loc.name); } }