Xamarin.iOS中的自定义SQLite函数

伊杜库尔

我正在Xamarin.iOS上使用Sqlite的自定义功能。我从这里得到了答案:在给定的半径范围内(Xamarin.Android)在地图上显示标记,但是我遇到了

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

在堆栈上搜索后,我发现这是一个解决方案:带有Mono的自定义函数SQLite,但提到的解决方案让我很难理解。

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

寿司宿醉

我使用流行的sqlite-net(由Frank A. Krueger编写),而反过来又使用SQLitePCLRaw.bundle_greenSQLitePCL.raw(均由Eric Sink编写)。

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

Xamarin.iOSSQLite用户定义函数(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设置表,负载/更新数据,.....

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

使用SQLitePCLRaw.ugly来创建和查询W / A SQLite的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.ToString()}', '{currentLongitude.ToString()}', barlocations.lat, barlocations.lng) <= 100 ;";
    var locs = dbRaw.query<BarLocations>(sql);
    foreach (var loc in locs)
    {
        Console.WriteLine(loc.name);
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章