Xamarin.iOS中的自定义SQLite函数

时间:2016-12-31 15:39:24

标签: ios sqlite xamarin xamarin.ios mono

我正在使用Xamarin.iOS上的Sqlite自定义功能。我从这里得到答案:Show markers on map within a given radius (Xamarin.Android)但是我遇到了

的问题
  

尝试JIT编译方法'(包装器本机到托管)   Mono.Data.Sqlite.SqliteFunction:ScalarCallback(intptr,int,intptr)'   使用--aot-only运行时。

在堆栈上搜索后,我发现这是一个解决方案:custom functions SQLite with Mono但解决方案提到我很难理解。

我不确定如何使用MonoPInvokeCallbackAttribute注释方法并将其设置为静态,因为SqliteFunction类中的方法被覆盖,因此无法使其成为静态。 如果有人可以帮助我理解该解决方案或在该解决方案上提供缺失的步骤,那将是很好的。

1 个答案:

答案 0 :(得分:2)

我使用受欢迎的$ctrl(由Frank A. Krueger提供),然后使用sqlite-netSQLitePCLRaw.bundle_green(均由Eric Sink提供)。

因此,您可以使用基于SQLitePCL.raw的API轻松设置和访问SQLite UDF。

基于SQLitePCLRaw.ugly的{​​{1}}用户定义函数(Xamarin.iOS):

SQLite

用法:

使用UDF设置表,加载/更新数据,.....

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);
}

使用sqlite-net-pcl创建和查询带有SQLite UDF

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
});