为了账号安全,请及时绑定邮箱和手机立即绑定

使用多年后更新数据库

使用多年后更新数据库

C#
米脂 2021-12-05 16:33:14
编辑 1:最后的故事示例多年前,我们创建了表格来计算我们的盒子里有多少产品。有两个简单的表:product (    code VARCHAR(16) PK,    length INT,    width INT,    height INT)box (    pkid INT IDENTITY(1,1),    barcode varchar(18),    product_code VARCHAR(16) FK,    quantity INT)还有两个相关的类:public struct Product{    public string Code { get; set; }    public int Length { get; set; }    public int Width { get; set; }    public int Heigth { get; set; }}public struct Box{    public int Id { get; set; }    public string BarCode { get; set; }    public Product Product { get; set; }    public int Quantity { get; set; }}多年后,我们需要将多个不同的产品放在同一个盒子里,所以我们现在需要这个:product (    code VARCHAR(16) PK,    length INT,    width INT,    height INT)-- box changedbox (    pkid INT IDENTITY(1,1),    barcode varchar(18))-- stock createdstock (    box_pkid INT M-PK FK,    product_code VARCHAR(16) M-PK FK,    quantity INT)和这个:public struct Product{    public string Code { get; set; }    public int Length { get; set; }    public int Width { get; set; }    public int Heigth { get; set; }}public struct Box{    public int Id { get; set; }    public string BarCode { get; set; }    public Dictionary<Product, int> Content { get; set; } // <-- this changed    public int Quantity { get; set; }}但多年后,我们有很多代码,可能在一些黑暗的地方重复,是离开合作者留下的。我是实习生,所以请教一下我以后的经历,以免以后遇到这种情况。更新我们的架构并保持数据完整性安全的解决方案是什么?即使数据库中有数百万行?示例: 2014 年,我们需要在一个盒子中存放 10 本罗密欧与朱丽叶书籍。如果我们有一些哈姆雷特的书,我们就会把它们放在另一个盒子里。罗密欧与朱丽叶的所有 10本书都是“相同”的产品(相同的封面、相同的内容、相同的参考文献)。今天,我们想将不同的莎士比亚书籍存放在同一个盒子里。或者可能是不同的爱情书籍。甚至罗密欧与朱丽叶的书籍和小雕像?将不同的产品放在一起:我们应该改变box table和Box class,不是吗?
查看完整描述

2 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

你有很多挑战;我会将他们分成两个高级别的小组。

首先,如何在代码级别更改应用程序,其次,如何将数据从旧模式迁移到新模式。

你如何改变你的代码?

第一个问题是:您能否 100% 确定您列出的类是访问和修改数据的唯一方式?是否有任何触发器、存储过程、批处理作业或其他应用程序?除了通过浏览数据库架构工件和代码库之外,我不知道有什么方法可以找到这一点。

在您“自己的”应用程序中,您有一个选择。扩展通常比修改界面更好。实际上,这意味着不是更改公共Product Product { get; set; }签名来处理字典,而是保留它并添加public Dictionary<Product, int> Content { get; set; }- 如果您可以保证旧方法仍然有效。这意味着有限地重写您的类的所有依赖项 - 您只需要担心需要了解一个盒子中可能有 1 个以上产品的客户。

这允许您遵循“很多小的更改,但现有代码继续工作”的模型;你可以通过功能切换等来管理它。它的风险要低得多 - 所以这里的教训是“设计你的解决方案对扩展开放,但对改变封闭”。

在这种情况下,这似乎是不可能的 - “set”方法可能没问题(您可以将其默认为“one product in a box”解决方案),但是“get”方法没有优雅的处理方式一个盒子里有超过 1 个产品的情况。如果这是真的,您更改类,并查找您的代码无法编译的所有实例,并遵循依赖链。

例如,在典型的 MVC 框架中,在这种情况下,您将更改模型;这应该会导致控制器报告编译错误。在解决该错误时,您几乎肯定会修改控制器方法的签名。这反过来应该打破这种看法。所以你遵循那个链条;这样做意味着您的架构更改将成为“大爆炸,全有或全无”的版本。这通常会给所有相关人员带来压力......

你如何释放你的变化?

这在很大程度上取决于您选择了两个选项中的哪一个。@gburton 的回答涵盖了数据库步骤;这些在两个代码选项中都是必需的。

第二个挑战是发布软件的新版本;例如,如果它是桌面客户端,则必须确保所有客户端在数据库更改的同时更新。这(通常)很可怕。如果它是一个 Web 应用程序,它通常会更容易一些 - 更少的客户端机器需要担心。


查看完整回答
反对 回复 2021-12-05
?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

安全地更新遗留系统是一个经典问题。我从你的帖子中猜测,没有一个很好的数据库安全开发副本,或者至少一个是最新的,或者你已经有了一个可以在这里申请的过程。

即使您显然使用的是 MS SQL Server,我还是以一种系统不可知的方式编写了这篇文章。

关键是要小心谨慎,并确保在出现问题时永远不会 100% 卡住。

  1. 备份旧数据库。确保您知道如何在不破坏任何内容的情况下执行此操作。

  2. 将该备份还原到新位置。

  3. 制定测试计划(这可能是工作中最长的部分)

  4. 对数据库的新副本进行更改(不要触摸实时副本)

  5. 运行您的测试计划以确保没有任何问题。

如果第 5 步显示一些错误,您只需解决它们。一旦完成,你就有了可怕的部分。备份恢复练习在这里至关重要。

  1. 备份实时数据库(您之前的备份可能已过时。您希望备份尽可能新鲜以减少数据丢失)

  2. 运行备份恢复练习以 100% 确保您可以恢复

  3. 将更改应用到实时数据库

  4. 重新运行你的测试

许多数据库引擎可以将数据库恢复到单个事务。如果可能,请考虑在步骤 6 中使用该过程。如何实现这一点将是一个单独的问题。


查看完整回答
反对 回复 2021-12-05
  • 2 回答
  • 0 关注
  • 163 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信