我正在设计一个相当复杂的系统。我们主要关心的问题之一是支持 SQL Server 点对点复制。这个想法是支持多个地理上分离的节点。

第二个问题是在中间层使用现代 ORM。我们的首选一直是实体框架,主要是因为开发人员喜欢使用它。(他们喜欢 LiNQ 支持。)

所以问题是这样的:

考虑到对等复制,我决定使用 uniqueidentifier 和默认值 newsequentialid() 作为每个表的主键。这似乎在避免键冲突和减少索引碎片之间提供了良好的平衡。

然而,事实证明当前版本的实体框架有一个 非常奇怪的限制: :如果实体的键列是唯一标识符 (GUID),则无法将其配置为使用数据库提供的默认值 (newsequentialid())。应用程序层必须生成 GUID 并填充键值。

所以这是辩论:

  1. 放弃实体框架并使用另一个 ORM:
    • 使用 NHibernate 并放弃 LiNQ 支持
    • 使用 linq2sql 并放弃未来的支持(更不用说在 DB 上绑定到 SQL Server)
  2. 放弃GUID并采用另一种PK策略
  3. 设计一种在应用层生成顺序 GUID(COMB?)的方法

我倾向于使用 linq2sql 的选项 1(我的开发人员非常喜欢 linq2[stuff])和选项 3。这主要是因为我对支持我们目标的复制方案同时从开发人员的角度保持理智的替代关键策略有些无知。

任何见解或意见将不胜感激。

有帮助吗?

解决方案

另一个选项(发布时不可用)是升级到 EF 4,它支持服务器生成的 GUID。

其他提示

我赞同克雷格的建议——选项 4。

您始终可以使用由中间层填充的 GUID 列作为主键(这是一个逻辑构造)。

为了避免大量索引(因此:表)碎片,使用一些其他键(最好是 INT IDENTITY 列)作为 CLUSTERING KEY - 这是一个物理数据库构造,可以与主键分开。

默认情况下,主键是集群键 - 但不一定如此。事实上,我通过在我“继承”的数据库上执行此操作,提高了性能并大大降低了碎片 - 添加一个 INT IDENTITY 列并将集群键放在那个小的、不断增加的、永不改变的 INT 上 - 效果非常好!

马克

啊?我认为你的三个选择都是错误的选择。考虑选项 4:

4) 使用实体框架 非顺序的, ,客户端生成的 GUID。

EF 无法看到数据库服务器生成的 GUID 对于框架本身插入的新行, 当然,但是您不需要在数据库服务器上生成 GUID。您可以在创建实体实例时在客户端上生成它们。GUID 的全部意义在于,在哪里生成它并不重要。至于由复制数据库生成的 GUID,EF 将很好地看到它们。

您的客户端 GUID 不会是连续的(使用 Guid.NewGuid()),但它们将是全球范围内的,并保证唯一。

我们在运输、生产软件中通过复制来做到这一点。它 工作。

为什么不使用身份列?如果您正在进行合并复制,您可以让每个系统从一个单独的种子开始并朝一个方向工作(例如,节点a从1开始加1,节点b从0开始减1)...

如果您确实坚持使用 NewSequentialID(),则可以使用存储过程。您可以将过程中的结果列绑定到适当的属性,一旦插入,SQL 生成的 GUID 将被反馈到对象中。

不幸的是,您必须为所有三个操作(插入、更新、删除)定义 SP,即使其他操作可以使用默认值正确完成。您还需要维护 SP 代码并确保在进行更改时它与您的 EF 模型同步,这可能会由于额外的开销而使此选项失去吸引力。

有一个分步示例,位于 http://blogs.msdn.com/bags/archive/2009/03/12/entity-framework-modeling-action-stored-procedures.aspx 这非常简单。

将 newseqid 与您自己的 orm 一起使用(这并不难)与 linq

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top