微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用Xamarin Forms,如何在共享代码中创建SQLite连接?

如何解决使用Xamarin Forms,如何在共享代码中创建SQLite连接?

我最近注意到有几篇文章提到了用通用代码创建sqlite连接。这是新的东西吗,因为我一直通过接口这样做:

是否有一种方法可以全部用通用代码完成,而不是在下面的需要使用Common,iOS和Android代码的实现中实现?

公用代码

[assembly: Dependency(typeof(IsqliteDB_iOS))]
namespace Memorise.iOS
{
    public class IsqliteDB_iOS : IsqliteDB
    {
        public (sqlite.sqliteConnection,bool) GetConnection(string _dbname)
        {
            bool newDb = false ;
            var sqliteFilename = _dbname;
            string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
            string libraryPath = Path.Combine(documentsPath,"..","Library");

            Debug.WriteLine(documentsPath);
            Debug.WriteLine(libraryPath);

            var path = Path.Combine(libraryPath,sqliteFilename);
            switch (_dbname)
            {
                case CONST.DB1Name:
                    if (File.Exists(path))
                    {
                        newDb = false;
                        File.Delete(path);
                    }
                    else
                    {
                        newDb = true;
                    }
                    File.copy(sqliteFilename,path);

                    break;
                case CONST.DB2Name:
                    if (File.Exists(path))
                    {
                        newDb = false;
                    }
                    else
                    {
                        newDb = true;
                        File.Create(path);
                    }

                    break;
                case CONST.DB3Name:
                    if (File.Exists(path))
                    {
                        newDb = false;
                    }
                    else
                    {
                        newDb = true;
                        File.copy(sqliteFilename,path);
                    }
                    break;
            }
           
            return (new sqlite.sqliteConnection(path),newDb);
        }
    }
}

iOS代码

[assembly: Dependency(typeof(sqliteDB1_Android))]

namespace Memorise.Droid
{
    public class sqliteDB1_Android : IsqliteDB1
    {
        public (sqlite.sqliteConnection,bool) GetConnection()
        {
            bool newDb;
            var sqliteFilename = "db1.db3";
            string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
            var path = Path.Combine(documentsPath,sqliteFilename);
            if (File.Exists(path))
            {
                newDb = false;
                File.Delete(path);
            }
            else
            {
                newDb = true;
            }
            FileStream writeStream = new FileStream(path,FileMode.OpenorCreate,FileAccess.Write);
            ReadWriteStream(Android.App.Application.Context.Assets.Open(sqliteFilename),writeStream);
            return (new sqlite.sqliteConnection(path),newDb);
        }

        void ReadWriteStream(Stream readStream,Stream writeStream)
        {
            int Length = 256;
            Byte[] buffer = new Byte[Length];
            int bytesRead = readStream.Read(buffer,Length);
            while (bytesRead > 0)
            {
                writeStream.Write(buffer,bytesRead);
                bytesRead = readStream.Read(buffer,Length);
            }
            readStream.Close();
            writeStream.Close();
        }
    }
}

Android代码

{{1}}

解决方法

我们可以利用FileSystem中的Xamarin.Essentials NuGet Package API来查找特定于平台的App Data Directory并以共享代码创建数据库连接。

var databasePath = Path.Combine(FileSystem.AppDataDirectory,"Database.db3");
var databaseConnection = new SQLiteConnection(databasePath);

我在有关Xamarin + SQLite的博客文章中更加深入:https://codetraveler.io/2019/11/26/efficiently-initializing-sqlite-database/

,

正如我看到的代码所示,您有两个数据库文件db1和db2。 此外,我可以看到db1是从Project Assests复制并粘贴到本地文件夹中的。 因此,您需要将db1.db3文件放入Resources文件夹中并将其标记为EmbeddedResource。这一步很重要。

可以简化其余代码,并将其更改为:-

    public DataManager()
    {
        var db1Path = Path.Combine(BasePath,CONST.DB1Name);
        newDb1 = !File.Exists(db1Path);
        if (newDb1)
        {
            var assembly = IntrospectionExtensions.GetTypeInfo(typeof(DataManager)).Assembly;
            Stream stream = assembly.GetManifestResourceStream("YourProjectName.Resources.db1.db3");
            using (var db1SourceStream = new FileStream(db1Path,FileMode.Create,FileAccess.ReadWrite))
            {
                stream.CopyTo(db1SourceStream);
                db1SourceStream.Close();
            }
        }
        db1 = new SQLiteConnection(db1Path);

        var db2Path = Path.Combine(BasePath,CONST.DB2Name);
        newDb2 = !File.Exists(db2Path);
        db2 = new SQLiteConnection(db2Path);
        db2.TimeExecution = true;
    }
,

通过使用sqlite-net-pcl,我成功地在.NET Standard库中建立了数据层,并在Xamarin Forms(iOS)和WPF中使用了它(但是您可能还可以将其扩展到Android和UWP。例如,

主要技巧是通过使用DI或平台if / else编译为数据库文件的应用程序本地存储指定不同的路径。

还有一个技巧,用于外键和删除级联(“ PRAGMA foreign_keys = ON;”),对于某些平台,在创建Connection对象之后仅调用一次就足够了,但是对于iOS而言,我需要将其更改为在每个需要外键的层叠功能的命令之前被调用。

    protected readonly SQLiteAsyncConnection db;
    protected abstract List<BaseMigration> Migrations { get; }

    public YourDB(string dbPath)
    {
        db = new SQLiteAsyncConnection(dbPath);
        db.ExecuteAsync("PRAGMA foreign_keys=ON;").Wait();
        //ExecuteMigrations(db).Wait();
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。