在C#和DB中创建Guid键的区别

在C#和DB中创建Guid键的区别,c#,sql,guid,C#,Sql,Guid,我们使用guid作为数据库中实体的主键。传统上,我们遵循的模式是让数据库在插入期间为实体设置ID,我认为这主要是因为这通常是使用自动递增字段或其他方式处理事情的方式 我越来越发现,在对象构造过程中,在代码中进行键赋值要容易得多,主要原因有两个: 您知道,一旦对象的构造函数运行,它的所有字段都已初始化。你永远不会有“半生不熟”的东西四处游荡 如果需要执行一批操作,其中一些操作取决于是否知道对象的键,则可以一次执行所有操作,而无需往返数据库 有没有令人信服的理由不这样做?也就是说,当使用guid作为

我们使用guid作为数据库中实体的主键。传统上,我们遵循的模式是让数据库在插入期间为实体设置ID,我认为这主要是因为这通常是使用自动递增字段或其他方式处理事情的方式

我越来越发现,在对象构造过程中,在代码中进行键赋值要容易得多,主要原因有两个:

  • 您知道,一旦对象的构造函数运行,它的所有字段都已初始化。你永远不会有“半生不熟”的东西四处游荡
  • 如果需要执行一批操作,其中一些操作取决于是否知道对象的键,则可以一次执行所有操作,而无需往返数据库
  • 有没有令人信服的理由不这样做?也就是说,当使用guid作为键时,是否有充分的理由将键分配留给数据库

    编辑: 很多人对是否应该将guid用于PKs(我知道这一点)有强烈的意见,但这并不是我问题的重点


    除了集群问题(如果您正确设置索引,这似乎不是一个问题),我还没有看到避免在应用程序层创建键的令人信服的理由。

    我认为您在客户端创建键做得很好。正如您所提到的,如果让db来做,您必须找到某种方法(真的想不出任何方法)来获取该密钥。如果您使用的是标识,则可以使用一些调用来获取为表创建的最新标识,但我不确定guid是否存在此类调用。

    在C#中执行此操作可能会冒重新分配guid并将其保存回数据库的风险。通过让数据库负责,可以保证此PK不会更改,也就是说,如果设置了适当的约束。话虽如此,您可以在C代码中设置类似的约束,以防止在分配完唯一id后更改该id,但您必须在所有应用程序中执行相同的操作…在我看来,在C代码中使用该id听起来比数据库更容易维护,因为数据库已经内置了防止更改主键的方法。

    guid对性能很糟糕


    我会把它留在数据库中,尤其是现在SQL Server已经不再导致插入页拆分,因为这些值是随机的,创建的每个NEWSEQUENTIALID都会比前一个大…唯一需要说明的是,它只能用作默认值

    我让空Guid作为该对象的指示器,虽然已构建,但尚未插入(或从中检索)数据库。

    如果您必须在GUI之外执行插入操作(考虑从其他供应商导入或从购买的公司导入数据并与数据合并),则不会自动分配GUID。这不是一个不可克服的问题,但它还是值得考虑的。< / P > >有趣的问题。 传统上我也使用DB分配的guid,但最近我正在开发一个Windows Mobile应用程序,SQL CE数据库不允许使用新的guid,所以我必须在代码中完成

    我使用SQL复制将数据从移动设备获取到服务器。在过去6个月中,我有40个SQL CE客户端将100000多条记录同步回SQL 2005服务器,而没有丢失或重复的guid

    所需的额外编码可以忽略不计,在插入之前了解guid的好处实际上降低了一些复杂性


    我没有做任何性能检查,所以除了性能之外,我看不出有任何理由不按照您的建议实施guid处理。

    正如SQLMenace所指出的,标准guid会对索引和分页产生负面影响。在C#中,您可以使用一点P/Invoke乐趣生成顺序guid,如NEWSEQUENTIALID()

    [DllImport("rpcrt4.dll", SetLastError = true)]
    static extern int UuidCreateSequential(out Guid guid);
    

    这样,您至少可以继续使用guid,但在生成guid的方式和位置上可以获得更大的灵活性。

    好的,是时候插话了。我想说,生成的用于保存到数据库的guid客户端是最好的方法——只要您碰巧使用guid作为pk,我只建议在一种情况下使用:断开连接的环境

    当您使用断开连接的模型进行数据传播(即PDA/手机应用程序、用于有限连接场景的笔记本电脑应用程序等)时,GUI作为PKs生成的客户端是最好的方法

    对于其他每一种情况,使用自动增量标识PKs可能会更好

    为什么??嗯,有几个原因。首先,通过使用一个跨行的聚集PK索引,您确实获得了很大的性能提升。GUID PK和聚集索引不能很好地结合在一起——即使使用NEWSEQUENTIALID,顺便说一句,我认为这完全忽略了GUID的意义。其次,除非您的情况迫使您不这样做(即,您必须使用一个断开连接的模型),否则您确实希望保持一切事务性,同时插入尽可能多的相关数据

    除了集群问题(如果您正确设置了索引,这似乎不是问题)

    作为索引的GUID总是非常混乱-没有“适当”的设置来避免这种情况(除非您在SQL Server引擎中使用NEWSEQUENTIALGUID函数)

    IMHO最大的缺点是大小-GUID是16字节,INT是4字节。PK不仅存储在主键的树中,而且还存储在每个非聚集索引项上

    对于几千个条目,这可能不会有太大的区别——但是如果您有一个包含数百万或数十亿个条目和几个非聚集索引的表,使用16字节GUID和4字节INT作为PK可能会在磁盘和RAM上产生巨大的空间差异


    Marc

    +1问得好,我自己也很好奇是否有这样或那样的缺点……这是一个很好的方法