【问题标题】:How to deploy a database file with a Xamarin.from app?如何使用 Xamarin.from 应用程序部署数据库文件?
【发布时间】:2017-08-25 02:04:59
【问题描述】:

我在我的项目中创建了一个包含一些数据的 sqlite 文件,但我不知道如何将它链接到我的应用程序。我希望数据可以加载到 Android 模拟器上。

我找到一个2015年发布的教程,它不再起作用,例如在新建一个FileAccessHelper类后找不到GetLocalFilePath函数。并且教程项目似乎使用了旧版本的 SQLite.net-PCL 包,因为教程项目中使用了 SQLite.Net.Platform.XamarinAndroid,而这个包不再存在。有什么想法吗?

http://arteksoftware.com/deploying-a-database-file-with-a-xamarin-forms-app/

这是教程中的代码:

[Activity (Label = "People", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity  
{
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);
        global::Xamarin.Forms.Forms.Init (this, bundle);

        string dbPath = FileAccessHelper.GetLocalFilePath ("people.db3");

        LoadApplication (new People.App (dbPath, new SQLitePlatformAndroid ()));
    }
}

FileAccessHelper.cs

public class FileAccessHelper  
{
    public static string GetLocalFilePath (string filename)
    {
        string path = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
        string dbPath = Path.Combine (path, filename);

        CopyDatabaseIfNotExists (dbPath);

        return dbPath;
    }

    private static void CopyDatabaseIfNotExists (string dbPath)
    {
        if (!File.Exists (dbPath)) {
            using (var br = new BinaryReader (Application.Context.Assets.Open ("people.db3"))) {
                using (var bw = new BinaryWriter (new FileStream (dbPath, FileMode.Create))) {
                    byte[] buffer = new byte[2048];
                    int length = 0;
                    while ((length = br.Read (buffer, 0, buffer.Length)) > 0) {
                        bw.Write (buffer, 0, length);
                    }
                }
            }
        }
    }
}

【问题讨论】:

  • 您应该使用“初始化脚本”而不是固定的 sqlite 文件 - 基本上是从代码初始化数据库的调用。由于(我想)您已经或多或少地使用数据库进行了管理(甚至可能是跨平台),因此它只会在您的第一次启动过程中添加一个步骤。

标签: c# sqlite xamarin xamarin.forms


【解决方案1】:

如果您想从 Xamarin.Forms 调用方法,您需要为每个平台实现一个接口,但我不会详细介绍此示例中的所有工作原理。以下是关于下面使用的 DependencyService 主题的 Xamarin 文档。

对于 Android,您需要将 DB 文件放在 Assets 文件夹中。这是您的 Android 项目中复制数据库并返回其路径的接口所需的代码:

[assembly: Xamarin.Forms.Dependency(typeof(FileAccessHelper))]
namespace MyNamespace.Droid
{
    class FileAccessHelper : MyXamarinFormsPage.IFileAccessHelper
    {
        public async Task<String> GetDBPathAndCreateIfNotExists()
        {
            String databaseName = "MyLite.db";
            var docFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
            var dbFile = Path.Combine(docFolder, databaseName); // FILE NAME TO USE WHEN COPIED
            if (!File.Exists(dbFile))
            {
                FileStream writeStream = new FileStream(dbFile, FileMode.OpenOrCreate, FileAccess.Write);
                await Forms.Context.Assets.Open(databaseName).CopyToAsync(writeStream);
            }
            return dbFile;
        }
    }
}

对于 UWP,您需要将 DB 文件放在根文件夹中。 UWP 项目中复制文件并返回路径的界面应如下所示:

[assembly: Xamarin.Forms.Dependency(typeof(FileAccessHelper))]
namespace MyNamespace.UWP
{
    public class FileAccessHelper : MyXamarinFormsPage.IFileAccessHelper
    {
        public async Task<String> GetDBPathAndCreateIfNotExists()
        {
            String filename = "MyLite.db";
            bool isExisting = false;
            try
            {
                StorageFile storage = await ApplicationData.Current.LocalFolder.GetFileAsync(filename);
                isExisting = true;
            }
            catch (Exception)
            {
                isExisting = false;
            }
            if (!isExisting)
            {
                StorageFile databaseFile = await Package.Current.InstalledLocation.GetFileAsync(filename);
                await databaseFile.CopyAsync(ApplicationData.Current.LocalFolder, filename, NameCollisionOption.ReplaceExisting);
            }
            return Path.Combine(ApplicationData.Current.LocalFolder.Path, filename);
        }
    }
}

对于 iOS,您需要将 DB 文件放在资源文件夹中。然后这是您的 iOS 项目中用于接口的代码:

[assembly: Xamarin.Forms.Dependency(typeof(FileAccessHelper))]
namespace MyNamespace.iOS
{
    public class FileAccessHelper : MyXamarinFormsPage.IFileAccessHelper
    {
        public async Task<String> GetDBPathAndCreateIfNotExists()
        {
            String databaseName = "MyLite.db";
            var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
            var path = Path.Combine(documentsPath, databaseName);
            if (!File.Exists(path))
            {
                var existingDb = NSBundle.MainBundle.PathForResource("MyLite", "db");
                File.Copy(existingDb, path);
            }
            return path;
        }
    }
}

然后可以通过执行以下操作从您的 Xamrin.Forms 项目中调用它:

public class MyXamarinFormsPage
{
    public MyXamarinFormsPage()
    {
        String DBPath = await DependencyService.Get<IFileAccessHelper>().GetDBPathAndCreateIfNotExists()
        //Store string for path
    }

    public interface IFileAccessHelper
    {
        Task<String> GetDBPathAndCreateIfNotExists();
    }
}

【讨论】:

  • 在构造函数中注入数据库路径非常好。我们“不需要”实现这样的架构来检索数据库路径。如果作者只使用 Android 则更是如此(根据他的问题,到目前为止似乎就是这种情况)。
  • @Kasper。任何机会链接到有关此方法的更多信息。我得到了无法创建接口错误的实例。你也在消费项目中上课,例如公共类 IFileAccessHelper 不是接口...
  • 所以我认为这应该是: public class FileAccessHelper : MyXamarinFormsPage.IFileAccessHelper
  • 这里有一些关于上面使用的依赖服务的文档。 docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/…
【解决方案2】:

尝试在您的 Android 项目中分配您的 dbpath 变量,并使用以下内容(忘记 FileAccessHelper 类):

[Activity (Label = "People", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity  
{
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);
        global::Xamarin.Forms.Forms.Init (this, bundle);

        // Retrieves the "AppHome"/files folder which is the root of your app sandbox on Android 
        var appDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
        // Locates your dbPath.
        string dbPath = Path.Combine(appDir , "people.db3");

        LoadApplication (new People.App (dbPath, new SQLitePlatformAndroid()));
    }
}

希望这会有所帮助!

【讨论】:

  • 在哪里可以找到 SQLitePlatformAndroid(),在 NuGet 商店中找不到包“SQLite.Net.Platform.XamarinAndroid”
猜你喜欢
  • 1970-01-01
  • 2014-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-28
  • 1970-01-01
  • 2015-08-08
相关资源
最近更新 更多