c# - NoSQL数据库中的架构迁移脚本

标签 c# .net mongodb azure-cosmosdb entity-framework-migrations

我有一个活跃的项目,一直使用C#, Entity Framework 和SQL Server。但是,随着NoSQL替代方案每天增加的可行性,我正在研究将项目切换为使用MongoDB的所有含义。

显然,主要的过渡障碍将归因于“无模式”。 MongoDB官方文档中的here很好地总结了C#等语言的含义。以下是最有用的相关段落(粗体添加):

Just because MongoDB is schema-less does not mean that your code can handle a schema-less document. Most likely, if you are using a statically typed language like C# or VB.NET, then your code is not flexible and needs to be mapped to a known schema.

There are a number of different ways that a schema can change from one version of your application to the next.

How you handle these is up to you. There are two different strategies: Write an upgrade script. Incrementally update your documents as they are used. The easiest strategy is to write an upgrade script. There is effectively no difference to this method between a relational database (SQL Server, Oracle) and MongoDB. Identify the documents that need to be changed and update them.

Alternatively, and not supportable in most relational databases, is the incremental upgrade. The idea is that your documents get updated as they are used. Documents that are never used never get updated. Because of this, there are some definite pitfalls you will need to be aware of.

First, queries against a schema where half the documents are version 1 and half the documents are version 2 could go awry. For instance, if you rename an element, then your query will need to test both the old element name and the new element name to get all the results.

Second, any incremental upgrade code must stay in the code-base until all the documents have been upgraded. For instance, if there have been 3 versions of a document, [1, 2, and 3] and we remove the upgrade code from version 1 to version 2, any documents that still exist as version 1 are un-upgradeable.



在SQL生态系统中用于管理/创建此类初始化或升级脚本的工具非常成熟(例如Entity Framework Migrations)

尽管在NoSQL世界中有similar toolshomemade scripts可用于此类升级(though some believe there should not be),但对于运行这些升级脚本的“何时”和“如何”的共识似乎较少。 Some建议部署后。不幸的是,当尝试读取C#模型已更改的现有数据时,这种方法(当不与增量更新结合使用时)会使应用程序处于无法使用的状态。

如果

"The easiest strategy is to write an upgrade script."



对于诸如C#这样的静态.NET语言,这确实是最简单/推荐的方法,在NoSql数据库中是否存在针对这些语言的代码优先模式迁移的现有工具?还是NoSql生态系统还不成熟?

如果您不同意MongoDB的建议,什么是更好的实现,并且您可以提供一些引用/示例以了解在哪里可以看到该实现?

最佳答案

精简版

Is "The easiest strategy is to write an upgrade script." is truly the easiest/recommended approach for static .NET languages like C#?



不,您可以这样做,但这不是NoSQL的优势。使用C#不会改变这一点。

are there existing tools for code-first schema migration in NoSql Databases for those languages?



不是我知道的。

or is the NoSql ecosystem not to that point of maturity?



它是无模式的。我认为这不是目标或成熟度。

警告事项

首先,我很怀疑只是将现有的关系模型推送到NoSql在一般情况下会解决比创建的问题更多的问题。

SQL用于处理关系和数据集,而noSQL则用于处理非关系数据:具有很少和/或软关系的“孤岛”。两者都擅长于所针对的目标,但它们擅长于不同的事情。 不可互换。在数据重新设计,团队思维定势和应用程序逻辑更改上花费大量精力,可能会使大多数先前的技术设计决策无效,并且影响力最终取决于体系结构系统属性,甚至可能取决于用户体验。

显然,这对您来说很有意义,但是肯定在提交之前先进行ROI数学。

处理架构变更

假设您确实有充分的理由进行切换,而模式变更管理是其中的关键,那么我建议不要与NoSQL的无模式本质抗争,而应该使用来接受它。接受您的数据将具有不同的架构。

不要升级脚本

..除非您知道应用程序数据集永远不会显着增长或更改。 The other SO post you referenced解释得很好。您只是,不能长期依靠来做到这一点,因此您仍然需要计划B。最好从它开始,并且如果确实是针对该特定情况进行的更简单的操作,则仅使用模式更新脚本。

我也许会补充说,一个好的NoSQL优化数据模型通常针对单项查找和写入进行了优化,而批量更新与SQL相比可能要重得多,即,更新单个字段可能需要重写更大的字段。本文档的+部分可能会处理一些引入的非规范化,以减少noSQL中的查找需求(甚至可能不是事务性的)。因此,在衡量升级停机时间时,NoSql中的“大”可能恰好比您预期的要小得多,并且发生得更快。

同时支持多种架构

实际上,由于并没有强制执行,因此实际上期望具有不同的并发“ Activity ”模式版本,这是您首先通过切换到NoSQL所要购买的核心功能。

理想地,以noSQL的心态,您的逻辑应该能够处理满足特定过程要求的任何输入数据。它应该取决于其所需的输入,而不取决于您的存储模型(对于依赖关系管理以降低复杂性也很普遍)也许逻辑仅取决于单一文档类型中的一些属性。只要某些其他字段已更改或添加了一些额外的数据(只要它们与要完成的给定工作无关),它就不会中断。绝对不应该在乎其他模型类型是否已更改。这种方法通常意味着要处理一些软值包(JSON/动态/字典/等)。

即使存储模型是无模式的,每个业务逻辑流程也都对输入模型(模式子集)抱有期望,并且应该验证输入模型是否可以使用给定的模型。沿模型保留的模式版本号在棘手的情况下也有帮助。

作为C#的人,我个人避免直接使用动态模型,而更喜欢创建强类型对象来包装每种动态存储类型。为了避免管理N个并发模式版本模型(差异最小)并不断升级逻辑层以支持新的模式版本,我将实现为给定实体的所有当前支持的模式版本的超集,并实现您需要的任何接口(interface)。当然,您可以添加N个以上的抽象层;)一旦一些旧的模式版本最终从数据中淘汰,您可以简化模型并获得强类型支持以覆盖所有依赖项。

同样,对于逻辑层,如果输入模型与执行预期逻辑的要求不匹配,则应具有回退或响应计划,这一点也很重要。这取决于应用程序的时间和位置,您可以在何时何地自动升级,接受丢弃,部分重置或必须定向到一些棘手的维修队列(如果没有自动切割机,则可以手动修复)或由于以下原因而不得不完全拒绝该请求不兼容。

是的,存在跨不同版本的模型集进行查询的问题,因此您也应始终考虑这些情况。您可能需要调整查询逻辑以分别查询不同的版本并合并结果(或接受部分结果,如果可以接受的话)。

当然,肯定要权衡考虑。

那么,迁移呢?

不利的一面(如果考虑迁移工具集的可用性)是因为您没有一个真正的架构来自动生成模型,或者它已更改,因为 C#模型是您当前支持的真相架构。实际上,这与代码优先的思维方式非常相似,但是没有迁移。

您可以实现一个传入模型管道,该管道会在读取模型时自动升级模型,从而减少需要在上游支持的架构版本的数量。我会说,这与您所获得的迁移非常接近。我不知道有任何工具可以自动为您执行此操作,并且不确定是否会这样做。需要权衡取舍,例如,某些使用数据的客户端可能会在不同的时间轴上进行升级等。升级到最新版本可能并不总是您想要的。

结论

根据定义,NoSQL不是SQL。两者都很酷,但是期望等效性或互换性必然会带来麻烦。

您仍然必须考虑和管理NoSQL中的架构,但是如果您想要一个真正的强制和保证架构,请考虑使用SQL。

关于c# - NoSQL数据库中的架构迁移脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49330096/

相关文章:

c# - Entity Framework 一对多问题

c# - 使用匿名方法

c# - 动态postbackurl

c# - 如何通过重复 get 和 setter 来缩短属性

python - 使用模拟 MongoDB 服务器进行单元测试

mongodb - MongoDB Atlas 中的多个集群与一个集群

c# - 如何禁用 DataGridView 键盘快捷键?

c# - WebAPI OData 预过滤扩展查询

.net - ASP.NET MVCF 可以与 Postgresql 数据库一起使用吗?

node.js - 已弃用的正文解析器?