2016-12-31 62 views
1

我正在使用Xamarin.iOS上的Sqlite自定義函數。我得到的答案從這裏:Show markers on map within a given radius (Xamarin.Android)但我遇到的Xamarin.iOS中的自定義SQLite函數

問題試圖JIT編譯方法「(包裝機設備到管理) Mono.Data.Sqlite.SqliteFunction:ScalarCallback(IntPtr的,INT,IntPtr的)' ,同時運行 - 只 - 。

在棧上搜索後,我發現這裏是一個解決方案:custom functions SQLite with Mono但解決方案提到有很難讓我理解。

我不確定如何使用MonoPInvokeCallbackAttribute註釋方法並將其設置爲靜態,因爲SqliteFunction類中的方法會被覆蓋,因此無法將其設置爲靜態。 如果有人能夠幫助我理解該解決方案或提供該解決方案中缺少的步驟,那將會很棒。

回答

1

我使用流行的sqlite-net(由Frank A. Krueger提供),它又使用SQLitePCLRaw.bundle_greenSQLitePCL.raw(均由Eric Sink提供)。

因此,您可以使用基於SQLitePCLRaw.ugly的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用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); 
    } 
} 
+0

1.我需要添加包「SQLitePCLRaw.ugly」嗎?因爲SQLitePCL.raw是它的更新版本。 2.「ugly.open」這裏的醜陋是什麼? 3. UDF代碼將在IOS部分或我可以在PCL – Iducool

+0

@Iducool 1寫)我目前使用SQLitePCLRaw的'V1.1.1。????'(難看,核心,生,綠色,sqlite3.ios_unified ,...)2)'ugly'來自'SQLitePCLRaw.ugly',一個'C'風格的C#API,它提供了最低級別的SQLite C#訪問,非常原始,因此被命名爲*醜陋* ... 3)雖然SQLite在這種情況下,UDF只是跨平臺的C#,而「MonoPInvokeCallbackAttribute」不是,只能在'Xamarin.iOS'中使用,所以'Xamarin.iOS'應用程序或庫或共享項目由前者之一引用。我通常使用一個共享的項目和'#如果__IOS__'開/關靜態UDF方法 – SushiHangover

+0

獲取異常屬性:未能從程序集加載類型「SQLitePCL.SQLite3Provider_sqlite3「SQLitePCLRaw.provider.sqlite3, – Iducool