C# 如何在已部署的应用程序中更改数据库设计?

C# 如何在已部署的应用程序中更改数据库设计?,c#,sql-server,database,deployment,C#,Sql Server,Database,Deployment,形势 我正在创建一个C#/WPF 4应用程序,使用SQL Compact Edition数据库作为实体框架的后端,并使用ClickOnce进行部署 我对使用数据库的应用程序是相当陌生的,尽管我不怀疑我在设计和构建原始数据库时会遇到很多问题。但是,我担心将来我需要添加或更改一些功能,这将要求我在部署数据库并且用户在数据库中有数据之后更改数据库设计 问题 是否有可能通过clickonce更新向用户推出更新的数据库设计,与代码更改的方式相同 如果我这样做了,用户的数据会受到怎样的影响 这种事情在现实中

形势

我正在创建一个C#/WPF 4应用程序,使用SQL Compact Edition数据库作为实体框架的后端,并使用ClickOnce进行部署

我对使用数据库的应用程序是相当陌生的,尽管我不怀疑我在设计和构建原始数据库时会遇到很多问题。但是,我担心将来我需要添加或更改一些功能,这将要求我在部署数据库并且用户在数据库中有数据之后更改数据库设计

问题

  • 是否有可能通过clickonce更新向用户推出更新的数据库设计,与代码更改的方式相同

  • 如果我这样做了,用户的数据会受到怎样的影响

  • 这种事情在现实中是如何做到的?哪些是最佳实践

  • 我认为,在最坏的情况下,我需要在数据库或程序设置中构建某种“版本”号,并创建一些例程来将用户当前的数据库版本迁移到新版本


    我很感激对我的问题有任何见解。非常感谢。

    在设计数据库以允许设计更改时,使用了一些“技巧”

    首先,许多数据库设计者创建视图进行编码,而不是直接对表进行编码。这允许更改表(拆分或合并等),而只需要更新视图。您可能需要研究这方面的技术


    其次,您确实可以将版本控制信息添加到数据库中(通常作为带有单个字段的“版本”表完成)。可以通过代码或脚本来更新数据库。我使用的一个系统会自动检查数据库版本,然后通过代码中的版本逐步更新模式,直到它与运行时所需的版本匹配。这是一项相当艰巨的任务。

    我认为在这种情况下,你的“最坏”情况实际上是一个很好的选择。在数据库中维护数据库版本,并让应用程序检查数据库,必要时更新数据库。如果您正确构建了更新程序,它应该能够维护用户的数据。根据更新情况,这可能涉及创建临时表以保存现有数据,并从中重新填充新版本的表。您可能能够在更新过程中使用新的模式,并简单地传输数据。这样可能会稍微容易一些——您可以使用文件命名来区分版本,并以这种方式触发更新代码。

    不幸的是,数据库的版本控制和更改管理与您使用其余代码所能做的相差甚远

    如果您只有一个内部环境,那么有很多工具可以帮助您(DBGhost、Red Gate有一个新的应用程序、一些部署管理应用程序),但它们都不是完整的解决方案imho,但大多数都足够好

    对于客户提供的解决方案,恐怕没有比最坏情况更好的了。只要在设计时考虑到灵活性——见赫比博士的答案

    这基本上不是一个已解决的问题。

    Brian Noyes的“使用ClickOnce的智能客户端部署”有一个关于此问题的精彩章节。(第5章) ISBN 978-0-32-119769-6

    他建议如下:

    if(ApplicationDeployment.CurrentDeployment.IsFirstRun) {
        MigrateData();
    }
    
    private void MigrateData() {
        string previousDb = Path.Combine(ApplicationDeployment.CurrentDeployment.DataDirectory, @".\pre\mydb.sdf");
    
        if(!File.Exists(previousDb))
            return;
    
        string oldConnString = @"Data Source=|DataDirectory|\.pre\mydb.sdf";
        string newConnString = @"Data Source=|DataDirectory|\mydb.sdf";
    
        //If you are using datasets perform any migration here, with the old and new table adapters.
        //Otherwise use an .sql data migration script.
        //Store the version of the database in the database, and check that in the beginning of your update script and GOTO the correct line in the SQL script.
    
    }
    

    一个常见的解决方案是在数据库中的某个地方包含一个版本号。如果您有一个包含杂项系统数据的表,请将其放入其中,或者创建一个包含一条记录的表,以保存DB版本号。然后,每当程序启动时,检查数据库版本是否低于预期版本。如果是这样,请执行所需的SQLCREATE、ALTER等命令以提高速度。为每个版本更改准备一个脚本或函数。因此,如果您看到数据库当前为版本6,并且代码期望版本8,则执行6到7更新和7到8更新

    我们在我工作的一个项目中使用的另一种方法是只提供模式,不提供带有代码的数据数据库。每次安装新版本时,安装程序都会安装此新空白数据库的最新副本。然后,当程序启动时,它会将用户当前的数据库模式与新的数据库模式进行比较,并确定需要动态更改哪些数据库。比如,如果在“引用模式”中,表Foo有一个名为Bar的列,而用户的当前数据库中没有列Bar,那么我们将生成一个“altertablefooaddbar…”并执行它。虽然编写程序的初稿来完成这项工作是相当多的工作,但一旦我们完成了,就几乎没有任何维护来保持数据库模式的最新。转换是即时完成的


    请注意,此方案不会处理需要更改数据值的DB更改,例如,如果您添加一个新列,则必须首先通过对其他表或类似表中的数据进行一些计算来填充该列。但是,如果您可以从旧数据生成新数据,那一定意味着新数据是冗余的,并且您的数据库没有规范化。我认为我们从来没有遇到过这种情况。

    我在Android应用程序中遇到过同样的问题,该应用程序使用SQLite数据库添加了一个表。我更改了数据库的名称,添加了一个版本扩展,如:Databasev1,删除了前一个,应用程序运行正常

    我刚刚更改了数据库的名称和这行代码中的名称

    private static final String DATABASE_NAME = "busesBogotaV2.db";
    
    当它要打开时,在DBManager中


    有人知道这个微不足道的解决方案是否会产生任何意外后果吗?

    +1我在一个系统上工作,该系统检查数据库版本,然后通过代码(SQL数据定义语句和操作数据库结构的代码的混合体,在本例中通过ADO)更新模式。我能想到的唯一选择是退出