3

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

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

所以问题来了:

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

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

所以这里是辩论:

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

我倾向于使用 linq2sql(我的开发人员真的很喜欢 linq2[stuff])和 3 的选项 1。这主要是因为我有点不知道支持我们目标的复制方案的替代关键策略,同时也让事情保持清醒开发人员的观点。

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

4

6 回答 6

8

我同意克雷格的建议 - 选项 4。

您始终可以使用由中间层填充的 GUID 列作为您的 PRIMARY KEY(这是一个 LOGICAL 构造)。

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

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

马克

于 2009-03-03T06:32:48.803 回答
5

嗯?我认为您的三个选项是错误的选择。考虑选项 4:

4) 将实体框架与非顺序的、客户端生成的 GUID 一起使用。

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

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

我们在具有复制功能的运输、生产软件中执行此操作。它确实有效。

于 2009-03-03T02:10:02.337 回答
4

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

于 2010-05-24T12:57:16.480 回答
0

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

于 2009-03-03T01:06:15.767 回答
0

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

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

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

于 2009-04-06T19:42:51.097 回答
0

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

于 2009-05-07T05:51:56.940 回答