【问题标题】:Xamarin.Android SQLite.NET duplicate column name: IDXamarin.Android SQLite.NET 重复列名:ID
【发布时间】:2016-08-10 08:16:19
【问题描述】:

我正在使用带有 SQLite 的 Xamarin 跨平台数据库,只有在发布模式下才会引发以下异常。在调试模式下永远不会抛出此异常。

Xamarin caused by: android.runtime.JavaProxyThrowable: SQLite.SQLiteException: duplicate column name: ID
  at SQLite.SQLite3.Prepare2 (SQLitePCL.sqlite3 db, System.String query) <0xa02a0d48 + 0x0005c> in <filename unknown>:0 
  at SQLite.SQLiteCommand.Prepare () <0xa02a0cc0 + 0x00023> in <filename unknown>:0 
  at SQLite.SQLiteCommand.ExecuteNonQuery () <0xa02a0a28 + 0x00023> in <filename unknown>:0 
  at SQLite.SQLiteConnection.Execute (System.String query, System.Object[] args) <0xa02a0548 + 0x0009f> in <filename unknown>:0 
  at SQLite.SQLiteConnection.MigrateTable (SQLite.TableMapping map) <0xa02a2bb8 + 0x00213> in <filename unknown>:0 
  at SQLite.SQLiteConnection.CreateTable (System.Type ty, CreateFlags createFlags) <0x9f25f170 + 0x004af> in <filename unknown>:0 
  at SQLite.SQLiteConnection.CreateTable[T] (CreateFlags createFlags) <0x9f25f0c0 + 0x0002b> in <filename unknown>:0 
  at lv.app.shared.DB.FailedUploadDBConn..ctor () <0x9f25a200 + 0x0005f> in <filename unknown>:0 
  at lv.app.android.services.InstantUploadService.OnCreate () <0x9f25a048 + 0x00027> in <filename unknown>:0 
  at Android.App.Service.n_OnCreate (IntPtr jnienv, IntPtr native__this) <0x9f259fe0 + 0x00037> in <filename unknown>:0 
  at (wrapper dynamic-method) System.Object:77405489-155e-4e61-bb78-110dfea670a3 (intptr,intptr)
    at md56f5b51080823ac84a85e457b8b35670a.InstantUploadService.n_onCreate(Native Method)
    at md56f5b51080823ac84a85e457b8b35670a.InstantUploadService.onCreate(InstantUploadService.java:30)
    at android.app.ActivityThread.handleCreateService(ActivityThread.java:3280)
    at android.app.ActivityThread.access$1900(ActivityThread.java:181)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1565)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:6145)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)

模型定义如下:

public class FailedUpload
{
    [PrimaryKey, AutoIncrement]
    public int ID { get; set; }

    [NotNull]
    public string Path { get; set; }

    [NotNull]
    public string FolderHash { get; set; }

    public FailedUpload () {}

    public FailedUpload (string path, string folderHash) {
        Path = path;
        FolderHash = folderHash;
    }
}

我已经定义了如下接口并在我的Android项目中实现了:

public interface ISQLite
{
    SQLiteConnection Connection { get; }
    void Delete ();
}

然后我使用依赖服务访问数据库:

public class FailedUploadDBConn
{
    SQLite.SQLiteConnection conn;

    public FailedUploadDBConn () {
        var dependency = DependencyService.Get<ISQLite> ();
        conn = dependency.Connection;
        conn.CreateTable<FailedUpload> (); //Exception gets thrown here.
    }

    //Other methods...

}

我应该做一些特定的事情以防止在发布模式下出现异常,还是只是捕获它而不做任何事情,或者它是 Xamarin 或 SQLite 中的错误?

【问题讨论】:

    标签: c# android sqlite xamarin


    【解决方案1】:

    您可能面临由链接器引起的(不正确的)优化。如果您从未从代码中引用 ID 属性,则链接器会将其删除。 您可以通过添加 [Preserve] attribute 来防止这种情况发生。

    此属性在 PCL 中不可用,但 linker 只对属性名称感兴趣,因此只需将以下类添加到您的 PCL:

    [AttributeUsage(AttributeTargets.All)]
    public class PreserveAttribute : Attribute
    {
        public bool AllMembers;
        public bool Conditional;
    
        public PreserveAttribute(bool allMembers, bool conditional)
        {
            AllMembers = allMembers;
            Conditional = conditional;
        }
    
        public PreserveAttribute()
        {
        }
    }
    

    另外:为什么要使用接口来注入 Sqlite.Net?它已经在跨平台工作,也可以在 PCL 中工作。您所需要的只是数据库的路径。见:https://developer.xamarin.com/guides/xamarin-forms/working-with/databases/#XamarinForms_PCL_Project

    【讨论】:

    • 该接口实际上是为了在每个平台上提供数据库路径而创建的(我遵循了您提供的确切指南)。它还具有用于开发目的的 Delete() 函数。
    猜你喜欢
    • 2019-08-02
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-31
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    相关资源
    最近更新 更多