【问题标题】:uwp sqlite add-migration crashes when updated to a new project更新到新项目时,uwp sqlite add-migration 崩溃
【发布时间】:2018-10-25 15:54:29
【问题描述】:

根据this documentation,我的 uwp 项目(带有实体框架)中有 SQLite 数据库。

我有一个针对周年纪念更新的 uwp 项目,所以当时这个文档很旧,我不得不在我的 uwp 项目中添加数据库代码和内容(而不是在 .Net 标准项目中)因此该项目已被许多用户通过商店安装,显然他们现在都在他们的设备上创建了一个数据库,比如说 Db1.db

一年后,我更新了我的应用并将其重新定位到创作者更新,我在一个新项目中进行了此操作,因为我必须对我的应用进行一些重大更改,所以我想要一个干净的项目开始,我添加了我的功能和还以与先前项目相同的数据库名称 Db1.db 相同的方式添加了数据库内容,然后我也将其发布到存储。

问题

现在,当我发布我的第二个包时,它在 DBContext.Migrate() 方法上崩溃了,该方法应该在 app.xaml.cs 的构造函数中,我知道它崩溃了因为数据库的名称相同,并且两个项目只有 1 个名为 MyFirstMigration 的迁移,并且不知何故会发生冲突并导致应用程序崩溃。我可以确认这一点,因为在我更新了我的第二个包(针对创建者更新)并将数据库名称更改为 Db2.db 之后不久,我没有崩溃,因为现在应用程序忽略用户设备上的旧数据库,只创建和使用新数据库,这不是最好的方法,因为我现有的用户无法访问他们在 Db1 中的数据,尽管新用户不会'不会受到影响,因为他们的所有数据仅在 Db2 中。

现在的情况是这样的:

用户组 1 这些用户的旧数据在 db1 中,新数据在 db2

用户组 2 这些用户的所有数据都在 db2

我可能会继续从头开始创建新项目以针对更新的 SDK,因为我喜欢从头开始进行更新的主要更新,这有助于我轻松地重构整个应用程序。那么如何在我的新项目中使用相同的数据库名称而不会使应用程序崩溃呢?我没有更改我的模型,我的模型将保持不变,并且无论我向商店发布多少新项目,我都只想继续使用 1 个数据库文件,应用程序应始终与该 1 个数据库文件通信。如果我只是从旧项目中复制 Migrations 文件夹并将其粘贴到新项目中并保持该迁移文件夹在我的新版本中保持一致,这可能吗?还是有其他方法?

另外请注意,现在在我的较新项目中,我的最低目标将是秋季创建者更新,因此我将使用 .net 标准库将我的数据库内容保存在那里,如我上面提到的文档中所述,所以我想继续使用db2.db 在我的新项目中也是如此。

【问题讨论】:

    标签: c# entity-framework sqlite uwp entity-framework-core-migrations


    【解决方案1】:

    这似乎是关于用户数据同步的问题。据我了解,您可以在新的秋季创建者更新 UWP 应用程序(我们将其称为新版本)中使用 db2.db,但是在用户将您的应用程序升级到新版本并在以下位置启动您的应用程序后第一次,你可以检查你的项目中是否存在db1.db,如果存在,你可以将db1.db中的数据复制到新的db2.db。

    这种方式看起来像是备份和恢复,但是在uwp应用中,更新不会删除你的db1.db,你只需要“恢复”或复制数据到你的新 db2.db 是使用 EF Core UWP 应用的新特性创建的,以后只需操作 db2.db 来存储用户数据,不再需要再次使用 db1.db

    ---更新---

    你是不是每次我创建一个新项目时都应该从以前的数据库中复制数据?意味着我不能使用相同的数据库文件?

    实际上,您只需从 db1.db 复制一次到 db2.db,因为您已将项目转换为使用 EF Core。在后面的版本中,由于你已经使用了EF Core,如果你新建一个项目更新,你可以直接使用db2.db,在我的测试中没有任何问题。

    如何检查旧数据库是否存在?

    既然知道了db文件名和文件位置,就可以通过查看db文件是否存在来判断旧db是否存在。

    private async Task<bool> IsFileExisted(string fileName)
    {
        var result= await ApplicationData.Current.LocalFolder.TryGetItemAsync(fileName);
        if (result == null)
        {
            return false;
        }
        return true;
    }
    

    由于您提供的document,似乎Migrate 方法是在App 的构造函数中调用的,这将导致难以使用异步方法。所以你可以把Migrate的代码放到App的OnLaunched事件处理器中。

     protected async override void OnLaunched(LaunchActivatedEventArgs e)
     {
         using (var db = new BloggingContext())
         {
             //db.Database.EnsureCreated();
             bool isExist = await IsFileExisted("db1.db");
             if (!isExist)
             {
                 db.Database.Migrate();
             }
    
         }
    
         Frame rootFrame = Window.Current.Content as Frame;
    
         // Do not repeat app initialization when the Window already has content,
         // just ensure that the window is active
         if (rootFrame == null)
         {
             // Create a Frame to act as the navigation context and navigate to the first page
             rootFrame = new Frame();
    
             rootFrame.NavigationFailed += OnNavigationFailed;
    
             if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
             {
                 //TODO: Load state from previously suspended application
             }
    
             // Place the frame in the current Window
             Window.Current.Content = rootFrame;
         }
    
         ...
    }
    

    如果你使用这个场景,你不需要创建 db2.db,你可以在你的新版本项目中使用 db1.db。

    现在我的最新项目使用 db2,所以我可以从这个项目连接到 db1 而不调用 migrate 函数吗? (因为 migrate 函数使应用程序崩溃。)然后只需将数据从 db1 复制到 db2。

    migrate 函数将上下文的任何未决迁移应用到数据库,如果数据库尚不存在,则将创建该数据库。如果数据库不存在,则需要使用 migrate 功能创建数据库。当然,如果 db1.db 存在,你可以连接到 db1 获取数据,而无需调用 migrate 函数。

    要实现它,可以按照document创建一个NewBloggingContext类继承模型库中的DbContext连接db1.db并复制数据。

    【讨论】:

    • 问题出在迁移选项上,正如我在问题中提到的,如果我在 Visual Studio 的新项目中创建新项目并上传该包,当用户更新应用程序并打开它时,应用程序崩溃,因为数据库名称冲突,您是否每次创建新项目时都应该从以前的数据库中复制数据?意味着我不能使用相同的数据库文件?现在我的最新更新正在使用 db2 ,所以如果我创建一个新项目更新我需要将数据从 db2 复制到新的 db3?似乎没有效率,我如何检查旧数据库是否存在? bcz 在迁移功能上崩溃。
    • 现在我的最新项目使用 db2,所以我可以从这个项目连接到 db1 而不调用 migrate 函数吗? (因为 migrate 功能使应用程序崩溃。)然后只需将数据从 db1 复制到 db2。
    • @touseef 我已经更新了我的答案,您可以查看,如果您有任何问题,请随时告诉我。
    • @BreezeLio 我如何将项目转换为 EFCore?在我的项目的两个版本中,我实际上使用的是相同的创建和使用数据库的方法,即使两个项目之间的 nuget 包版本相同,但是现在当我创建新版本时,它可能会使用 efcore,因为我将使用.net 标准库,但在 db1 和 db2 之间,我认为我使用的任何 EF 版本都是相同的
    • 在上面的代码中,您检查 db1 是否存在,然后如果它不执行迁移(创建 db)在哪个 db 上? db1 还是 db2?在您的示例中,dbcontext 代表哪个连接?
    猜你喜欢
    • 1970-01-01
    • 2019-04-12
    • 2020-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多