Guid là gì C

Tôi thường sử dụng ID gia tăng tự động làm Khóa chính trong cơ sở dữ liệu. Tôi đang cố gắng tìm hiểu những lợi ích của việc sử dụng GUID. Tôi đã đọc bài viết này: https://betterexplained.com/articles/the-quick-guide-to-guids/

Tôi nhận ra rằng các GUID này được sử dụng để xác định các đối tượng ở cấp ứng dụng. Có phải chúng cũng được lưu trữ như là khóa chính ở cấp cơ sở dữ liệu. Ví dụ, giả sử tôi có lớp sau: public class Person{public GUID ID;public string Name;..//Person Methods follow}

Nói rằng tôi muốn tạo một người mới trong bộ nhớ và sau đó chèn Người vào cơ sở dữ liệu. Tôi chỉ có thể làm điều này: Person p1 = new Person();p1.ID=GUID.NewGUID();PersonRepository.Insert(p1);

Giả sử tôi có cơ sở dữ liệu chứa hàng triệu và hàng triệu hàng với GUID làm Khóa chính. Điều này sẽ luôn luôn là duy nhất? Tôi thậm chí có hiểu chính xác GUID không?

Tôi đã đọc bài viết này sớm hơn: http : //enterpriseccraft Skill.com/2014/11/15/cqs-with-database-generated-ids/ . Nó làm tôi bối rối một chút vì nó dường như đề xuất một phương tiện hạnh phúc giữa GUID và số nguyên làm Khóa chính.

Chỉnh sửa 11/06/18

Tôi đã tin rằng Guids phù hợp hơn ints cho yêu cầu của tôi. Tôi đang sử dụng CQRS nhiều hơn những ngày này và GUID phù hợp hơn.

Tôi nhận thấy rằng một số nhà phát triển mô hình hóa các GUID dưới dạng chuỗi trong mô hình miền, ví dụ như ở đây: https://github.com/dotnet-arch architecture / eShopOnContainers / blob / dev / src / Service / ORdering / Domain.DAggregatesModel / Banger Người mua.cs - trong trường hợp này: IdentityGuid là một GUID được mô hình hóa dưới dạng chuỗi. Có bất kỳ lý do để làm điều này ngoài những gì được nêu ở đây: Sử dụng một đối tượng giá trị tùy chỉnh hoặc Hướng dẫn làm định danh thực thể trong một hệ thống phân tán? . Việc mô hình hóa GUID thành một chuỗi là "bình thường" hay tôi nên mô hình hóa nó như một GUID trong mô hình và cơ sở dữ liệu?

GUID theo định nghĩa "IDentifier duy nhất toàn cầu". Có một khái niệm tương tự nhưng hơi khác trong Java được gọi là UUID "IDentifier duy nhất toàn cầu". Các tên có thể hoán đổi cho nhau để sử dụng thực tế.

GUID là trọng tâm trong cách Microsoft hình dung phân cụm cơ sở dữ liệu để hoạt động và nếu bạn cần kết hợp dữ liệu từ các nguồn được kết nối đôi khi, chúng thực sự giúp ngăn chặn xung đột dữ liệu.

Một số sự kiện Pro-GUID:

  • GUID ngăn va chạm quan trọng
  • GUID giúp hợp nhất dữ liệu giữa các mạng, máy, v.v.
  • SQL Server có hỗ trợ cho GUIDS bán tuần tự để giúp giảm thiểu phân mảnh chỉ mục ( ref , một số cảnh báo)

Một số Ugliness với GUID

  • Chúng lớn, mỗi 16 byte
  • Chúng không theo thứ tự, vì vậy bạn không thể sắp xếp ID và hy vọng nhận được thứ tự chèn như bạn có thể trên id tăng tự động
  • Chúng cồng kềnh hơn khi làm việc, đặc biệt là trên các tập dữ liệu nhỏ (như tra bảng)
  • Việc triển khai GUID mới mạnh mẽ hơn trên SQL Server so với trong thư viện C # (bạn có thể có GUIDS tuần tự từ SQL Server, trong C # là ngẫu nhiên)

GUID sẽ làm cho các chỉ mục của bạn lớn hơn, do đó chi phí không gian đĩa của việc lập chỉ mục một cột sẽ cao hơn. GUID ngẫu nhiên sẽ phân đoạn các chỉ mục của bạn.

Nếu bạn biết bạn sẽ không đồng bộ hóa dữ liệu từ các mạng khác nhau, GUID có thể mang nhiều chi phí hơn giá trị.

Nếu bạn có nhu cầu nhập dữ liệu từ các máy khách đôi khi được kết nối, chúng có thể mạnh mẽ hơn rất nhiều để ngăn chặn các xung đột chính so với việc dựa vào cài đặt phạm vi trình tự cho các máy khách đó.

Điều này sẽ luôn luôn là duy nhất?

Luôn luôn? không, không phải lúc nào cũng vậy; đó là một chuỗi hữu hạn của các bit.

Giả sử tôi có cơ sở dữ liệu chứa hàng triệu và hàng triệu hàng với GUID làm Khóa chính.

Hàng triệu và hàng triệu, bạn có thể an toàn. Một triệu triệu, và khả năng va chạm trở nên đáng kể. Tuy nhiên, có một tin tốt: bạn đã hết dung lượng đĩa vào thời điểm đó.

Tôi có thể làm điều này?

Bạn có thể; nó không phải là một ý tưởng hoàn toàn tốt Mô hình miền của bạn thường không nên tạo số ngẫu nhiên; chúng nên là đầu vào cho mô hình của bạn.

Ngoài ra, khi bạn đang xử lý một mạng không đáng tin cậy, nơi bạn có thể nhận được các tin nhắn trùng lặp, một UUID được tạo một cách xác định sẽ bảo vệ bạn khỏi có các thực thể trùng lặp. Nhưng nếu bạn chỉ định một số ngẫu nhiên mới cho mỗi số, thì bạn có nhiều việc phải làm để xác định sự trùng lặp.

Xem mô tả về uuid dựa trên tên trong RFC 4122

Việc mô hình hóa GUID thành một chuỗi là "bình thường" hay tôi nên mô hình hóa nó như một GUID trong mô hình và cơ sở dữ liệu?

Tôi không nghĩ nó quan trọng lắm. Đối với hầu hết các mô hình miền của bạn, nó là một định danh ; truy vấn duy nhất bạn yêu cầu là liệu nó có giống với một số định danh khác hay không. Mô hình miền của bạn thường sẽ không nhìn vào biểu diễn trong bộ nhớ của một mã định danh.

Nếu GUID có sẵn dưới dạng "loại nguyên thủy" trong cài đặt không biết tên miền của bạn, tôi sẽ sử dụng nó; nó cho phép bối cảnh hỗ trợ để chọn tối ưu hóa phù hợp có thể có sẵn.

Tuy nhiên, điều bạn nên nhận ra là sự thể hiện của mã định danh, cả trong bộ nhớ và trong bộ lưu trữ, là một quyết định mà bạn đang đưa ra khi thực hiện và do đó bạn nên thực hiện các bước để đảm bảo rằng dấu chân của mã được ghép với điều đó quyết định là nhỏ - xem  Parnas 1972 .

HƯỚNG DẪN hoặc  UUID rất có thể là duy nhất vì cách chúng được tạo và chúng cung cấp một cách an toàn để đảm bảo tính duy nhất mà không phải liên lạc với cơ quan trung ương.

Lợi ích của GUID là khóa chính:

  • Bạn có thể sao chép dữ liệu giữa các phân đoạn khác nhau của cụm và không cần phải lo lắng về các va chạm PK.
  • Nó cho phép bạn biết khóa chính của mình trước khi bạn chèn bất kỳ bản ghi nào.
  • Đơn giản hóa logic giao dịch để chèn hồ sơ con.
  • Không thể dễ dàng đoán ra.

Trong ví dụ bạn cung cấp: Person p1 = new Person();p1.ID = GUID.NewGUID();PersonRepository.Insert(p1);

Chỉ định GUID trước thời gian chèn có thể lưu một chuyến đi khứ hồi vào cơ sở dữ liệu khi chèn các bản ghi con liên tiếp và cho phép bạn cam kết chúng trong cùng một giao dịch. Person p2 = new Person();p2.ParentID = p1.ID PersonRepository.Insert(p2);

Những bất lợi cho GUID là khóa chính:

  • Chúng có dung lượng lớn 16 byte nghĩa là chúng sẽ tiêu tốn nhiều dung lượng hơn khi các chỉ mục và khóa ngoại được thêm vào.
  • Họ không sắp xếp tốt vì về cơ bản chúng là những con số ngẫu nhiên.
  • Chỉ số sử dụng là rất, rất, rất xấu.
  • Rất nhiều lá di chuyển.
  • Họ rất khó nhớ.
  • Họ rất khó để diễn đạt bằng lời.
  • Họ có thể làm cho URL khó đọc hơn.

Nếu ứng dụng của bạn không có nhu cầu sắp xếp hoặc phân cụm, tốt nhất bạn nên sử dụng loại dữ liệu nhỏ hơn, đơn giản hơn như int hoặc bigint.

Nhiều cơ sở dữ liệu có triển khai nội bộ của mình mà cố gắng để giảm thiểu những vấn đề lưu trữ do của GUID và SQL Server thậm chí còn có một chức năng newsequentialid để giúp đỡ với việc đặt hàng của UUID của phép sử dụng tốt hơn các chỉ số và họ thường có những đặc điểm hiệu suất tốt hơn.

Ngoài ra, từ góc độ của người kiểm tra, người dùng hoặc nhà phát triển làm việc với ứng dụng, sử dụng ID qua GUID sẽ cải thiện đáng kể giao tiếp. Hãy tưởng tượng bạn phải đọc một GUID qua điện thoại.

Cuối cùng, trừ khi các cụm phân cụm hoặc làm mờ các URL quy mô lớn là một yêu cầu thực tế hơn để gắn với các ID tăng tự động.

Tôi muốn nói không, đừng sử dụng GUID làm khóa chính. Tôi thực sự đang đối phó với một DB như vậy và chúng là một trong những nguyên nhân chính gây ra các vấn đề về hiệu năng.

Thêm 12 byte cộng lại nhanh chóng; hãy nhớ rằng, hầu hết các PK sẽ là FK trong các bảng khác và chỉ có ba FK trong một bảng mà bạn hiện có thêm 48 byte cho mỗi hàng. Điều đó cộng lại trong bảng và trong các chỉ mục. Nó cũng thêm vào trong I / O đĩa. 12 byte thêm đó cần phải được đọc và viết.

Và nếu bạn không sử dụng các hướng dẫn tuần tự và các PK được phân cụm (đó là những gì xảy ra theo mặc định), đôi khi SQL sẽ phải di chuyển toàn bộ các trang dữ liệu xung quanh để vắt nhiều hơn vào đúng "điểm". Đối với một cơ sở dữ liệu giao dịch cao với nhiều phần chèn, cập nhật và xóa, mọi thứ sẽ chậm lại.

Nếu bạn cần một số loại định danh duy nhất để đồng bộ hóa hoặc một cái gì đó, hãy thêm một cột hướng dẫn. Đừng biến nó thành PK.

Person p1 = new Person();p1.ID=GUID.NewGUID();PersonRepository.Insert(p1);

Đây là lý do quan trọng nhất để sử dụng GUID.

Việc bạn có thể tạo một id duy nhất mà không cần mã của bạn biết hoặc liên lạc với lớp kiên trì của bạn là một lợi ích rất lớn.

Bạn có thể chắc chắn rằng đối tượng Person bạn vừa tạo trên máy chủ, điện thoại pc, máy tính xách tay, thiết bị ngoại tuyến hoặc bất cứ thứ gì là duy nhất trên tất cả các máy chủ của bạn trên toàn thế giới được phân phối.

Bạn có thể dán nó vào bất kỳ loại cơ sở dữ liệu rdb hoặc no-sql, tệp nào, gửi nó đến bất kỳ dịch vụ web nào hoặc vứt nó đi ngay lập tức khi không cần thiết

Không, bạn sẽ không bao giờ có được một vụ va chạm.

Có chèn có thể chậm hơn một chút vì chỉ số có thể cần phải được xử lý.

Có nó lớn hơn một int.

  • chỉnh sửa. đã phải bắn ra trước khi kết thúc.

Tôi biết nhiều người cảm thấy mạnh mẽ về auto inc ints và đây là một chủ đề gây tranh cãi với các DBA

Nhưng tôi thực sự không thể tuyên bố đủ mạnh mẽ về những hướng dẫn vượt trội. Bạn nên sử dụng các hướng dẫn theo mặc định trong bất kỳ ứng dụng nào.

auto inc ints có nhiều sai sót

  • Bạn sử dụng db phân phối No-Sql. Bạn chỉ đơn giản là không thể nói chuyện với tất cả các trường hợp khác để tìm ra số tiếp theo là gì.
  • Bạn sử dụng một hệ thống xếp hàng tin nhắn. Mọi thứ cần ID trước khi chúng vào db
  • Bạn đang tạo một số mục và chỉnh sửa chúng trước khi lưu. Mỗi người cần một id trước khi bạn nhấn db
  • Bạn muốn xóa và chèn lại hàng. Hãy chắc chắn rằng bạn không đếm id id tự động của bạn và chạy ra ngoài!
  • Bạn muốn không tiết lộ số lượng Đơn đặt hàng bạn đã thực hiện trong năm nay cho mọi người dùng
  • Bạn muốn chuyển dữ liệu ẩn danh từ sản xuất sang kiểm tra và giữ nguyên các mối quan hệ. Nhưng không xóa tất cả các dữ liệu thử nghiệm hiện có.
  • Bạn muốn hợp nhất sản phẩm của người thuê nhà của bạn vào cơ sở dữ liệu nhiều người thuê nhưng mọi người đều có một đơn hàng 56.
  • Bạn tạo các đối tượng vẫn tồn tại nhưng phù du. (đơn đặt hàng chưa hoàn thành) một lần nữa, không sử dụng hết số int của bạn với những thứ không còn tồn tại.

Danh sách này là vô tận và tất cả chúng đều là những vấn đề thực sự xảy ra với mọi người mọi lúc. Không giống như hết dung lượng đĩa vì cols FK lớn hơn một chút

Cuối cùng, vấn đề lớn với ints là bạn hết chúng !!! ok trong lý thuyết bạn không, có tải. Nhưng trong thực tế, bạn làm bởi vì mọi người không coi chúng như những con số ngẫu nhiên không có ý nghĩa. họ làm những việc như

  • oh tôi không muốn khách hàng nghĩ rằng chúng tôi là người mới bắt đầu từ 10.000
  • Tôi đã phải nhập một tải dữ liệu vì vậy tôi chỉ cần tăng hạt giống lên 1m để chúng tôi biết những gì được nhập khẩu
  • chúng ta cần loại dữ liệu. mỗi kỳ bắt đầu từ một triệu tiếp theo để chúng ta có thể sử dụng các chữ số đầu tiên làm số ma thuật
  • Tôi đã xóa và nhập lại tất cả dữ liệu với id mới. Có ngay cả nhật ký kiểm toán.
  • sử dụng số này, là khóa tổng hợp, làm id của thứ khác
Tôi nhận ra rằng các GUID này được sử dụng để xác định các đối tượng ở cấp ứng dụng. Có phải chúng cũng được lưu trữ như là khóa chính ở cấp cơ sở dữ liệu.

Đó là nơi bạn nên dừng lại, ngay tại đó và suy nghĩ lại.

Khóa chính cơ sở dữ liệu của bạn KHÔNG BAO GIỜ có ý nghĩa kinh doanh. Nó nên là vô nghĩa theo định nghĩa.

Vì vậy, hãy thêm GUID làm khóa doanh nghiệp của bạn và khóa chính thông thường (thường là int dài) làm khóa chính của cơ sở dữ liệu. Bạn luôn có thể đặt một chỉ mục duy nhất trên GUID để đảm bảo tính duy nhất.

Đó là lý thuyết cơ sở dữ liệu nói chuyện tất nhiên, nhưng nó cũng là thực hành tốt. Tôi đã xử lý các cơ sở dữ liệu trong đó các khóa chính có ý nghĩa kinh doanh (một khách hàng đã nghĩ sẽ lưu một số tài nguyên cơ sở dữ liệu bằng cách sử dụng chúng làm số nhân viên, số khách hàng, v.v.) và nó luôn dẫn đến rắc rối.

Luôn sử dụng cơ sở dữ liệu được tạo, tự động tăng khóa chính (PK).

Tại sao nên sử dụng tự động tăng thay vì GUID / UUID?

  • GUID (UUID) không ngăn chặn các va chạm chính vì chúng không phải là duy nhất và không có cách nào để làm cho chúng trở nên độc nhất vì chúng được tạo từ nhiều nguồn.
  • GUID không giúp hợp nhất vì chúng làm tăng đáng kể quá trình hợp nhất đã tốn thời gian với các cột PK và FK không nguyên, rất dài, cần rất nhiều thời gian để xử lý. Hãy nhớ rằng đối với hầu hết các PK, sẽ có ít nhất 1 bảng khác có ít nhất 2 khóa có cùng kích thước: đó là PK riêng và FK trở lại bảng đầu tiên. Tất cả phải được giải quyết trong một hợp nhất.

Nhưng làm thế nào để xử lý các mảnh vỡ, cụm, vv?

  • Tạo các PK nhiều cột được tạo thành từ các cột riêng biệt xác định từng phân đoạn / cụm / cơ sở dữ liệu / bất cứ thứ gì quản lý các khóa tăng tự động của chính nó. Ví dụ...

PK 3 cột cho bảng phân cụm có thể là ...   DB | SH | KEY     |----|----|---------| 01 | 01 | 1234567 |

Nhưng còn ...?

  • Nhiều chuyến đi đến cơ sở dữ liệu - Hầu hết các ứng dụng không cần xác định duy nhất một bản ghi được tạo cho đến khi nó được chèn vào cơ sở dữ liệu vì luồng / phiên / bất cứ thứ gì chỉ hoạt động trên một lần. Nếu ứng dụng thực sự cần khả năng này, hãy sử dụng ứng dụng tạo PK tạm thời không được gửi đến cơ sở dữ liệu . Để cơ sở dữ liệu sau đó đặt PK tự động tăng lên trên hàng khi nó được chèn. Các phần chèn sẽ sử dụng PK tạm thời, trong khi các bản cập nhật và xóa sẽ sử dụng PK vĩnh viễn được chỉ định bởi cơ sở dữ liệu.
  • Hiệu suất - Máy tính có thể xử lý các số nguyên đơn giản nhanh hơn nhiều so với bất kỳ thứ gì khác do miền lớn hơn rất nhiều nếu các giá trị có thể có trên mỗi phần tử trong GUID (37) so với số nguyên (10). Cũng cần nhớ rằng mỗi ký tự trong GUID trước tiên phải được chuyển đổi thành số để được CPU thao tác.

Các lỗi phổ biến của các khóa chính PK chỉ có một mục đích ... để xác định hoàn toàn duy nhất một hàng trong bảng. Bất cứ điều gì khác là một lạm dụng quá phổ biến.

Phát hiện hồ sơ mất tích

  • Hồ sơ mất tích không thể được phát hiện bằng cách nhìn vào PK. Bless QA ít nhất là cố gắng đảm bảo chất lượng dữ liệu. Tuy nhiên, họ và các lập trình viên thiếu hiểu biết về cách các khóa trong các hệ thống cơ sở dữ liệu hiện đại được gán thường khiến họ hiểu nhầm rằng một số bị thiếu trong PK tự động tăng có nghĩa là thiếu dữ liệu. Nó không vì ...
  • Để thực hiện, các hệ thống cơ sở dữ liệu phân bổ các khối số theo 'chuỗi' (lô, phạm vi) để giảm thiểu các chuyến đi đến cơ sở dữ liệu thực tế trong bộ lưu trữ. Kích thước của các dãy số này thường nằm dưới sự kiểm soát của DBA nhưng có thể không điều chỉnh được trên cơ sở mỗi bảng.
  • Điểm đáng chú ý là ... các số không được sử dụng từ các chuỗi này không bao giờ được trả về cơ sở dữ liệu nên luôn có các khoảng trống trong các số PK.
  • Tại sao có những con số không sử dụng bạn yêu cầu? Bởi vì một loạt các hành động bảo trì cơ sở dữ liệu có thể khiến các chuỗi bị bỏ qua. Đây là những thứ như khởi động lại, tải lại số lượng lớn các bảng, một số loại phục hồi từ bản sao lưu và một số hoạt động khác.

Sắp xếp

  • Sắp xếp theo PK rất dễ bị lỗi vì hầu hết mọi người sẽ nghĩ rằng nó liệt kê các hàng theo thứ tự chúng được tạo và tương ứng với thời gian. Chủ yếu, nhưng không cần thiết.
  • Các công cụ cơ sở dữ liệu được tối ưu hóa để đạt hiệu suất tối đa và điều đó có thể có nghĩa là trì hoãn việc chèn kết quả của một giao dịch phức tạp kéo dài để chèn các giao dịch đơn giản ngắn, "ngoài luồng".

Giống như bất cứ điều gì, có những lợi thế và bất lợi để làm điều này:

Tốt:

  1. Các khóa của bạn luôn có cùng độ dài (cơ sở dữ liệu rất lớn có thể có các khóa rất lớn)
  2. Tính duy nhất được đảm bảo khá nhiều - ngay cả khi bạn tạo chúng từ một hệ thống riêng biệt và / hoặc chưa đọc ID cuối cùng từ cơ sở dữ liệu

Những người xấu:

  1. Như đã đề cập rất nhiều ở trên - chỉ mục lớn hơn và lưu trữ dữ liệu.
  2. Bạn không thể đặt hàng bằng ID, bạn phải đặt hàng bằng thứ khác. Nhiều chỉ số hơn, có thể kém hiệu quả hơn.
  3. Chúng ít người đọc được. Số nguyên thường dễ phân tích, ghi nhớ và gõ cho mọi người. Sử dụng GUID làm ID trong mệnh đề WHERE trên nhiều bảng đã tham gia có thể khiến đầu bạn tan chảy.

Giống như mọi thứ, hãy sử dụng chúng khi thích hợp, đừng giáo điều - trong nhiều tình huống, số nguyên tự động tăng sẽ tốt hơn, đôi khi GUID rất tuyệt.

Có, bạn có thể sử dụng GUID làm khóa chính. Mặt trái là kích thước và sự phân mảnh nhanh chóng của chỉ số.

Trừ khi bạn cần tính duy nhất trên các cơ sở dữ liệu (ví dụ: một cụm) số nguyên được ưu tiên.

Đây là vấn đề của tôi về vấn đề này - giải pháp là một ngôi nhà nửa chừng giữa giá trị GUID và int, tận dụng tốt nhất cả hai.

Lớp tạo ra một giá trị Id giả ngẫu nhiên (nhưng tăng dần theo thời gian), tương tự như Comb GUID .

Ưu điểm chính là nó cho phép các giá trị Id được tạo trên máy khách, thay vì sử dụng các giá trị tăng tự động được tạo trên máy chủ (yêu cầu một chuyến đi khứ hồi) với rủi ro gần như bằng 0 của các giá trị trùng lặp.

Các giá trị được tạo chỉ sử dụng 8 byte thay vì 16 cho GUID và không phụ thuộc vào một thứ tự sắp xếp cơ sở dữ liệu cụ thể (ví dụ: Sql Server cho GUID ). Các giá trị có thể được mở rộng để sử dụng toàn bộ phạm vi dài không dấu, nhưng điều này sẽ gây ra sự cố với bất kỳ cơ sở dữ liệu hoặc kho lưu trữ dữ liệu nào khác chỉ có các kiểu số nguyên đã ký. public static class LongIdGenerator{    // set the start date to an appropriate value for your implementation     // DO NOT change this once any application that uses this functionality is live, otherwise existing Id values will lose their implied date    private static readonly DateTime PeriodStartDate = new DateTime(2017, 1, 1, 0, 0, 0, DateTimeKind.Utc);    private static readonly DateTime PeriodEndDate = PeriodStartDate.AddYears(100);    private static readonly long PeriodStartTicks = PeriodStartDate.Ticks;    private static readonly long PeriodEndTicks = PeriodEndDate.Ticks;    private static readonly long TotalPeriodTicks = PeriodEndTicks - PeriodStartTicks; // ensures that generated Ids are always positve    private const long SEQUENCE_PART_PERMUTATIONS = 0x7FFFFFFFFFFF; private static readonly Random Random = new Random(); private static readonly object Lock = new object();    private static long _lastSequencePart; public static long GetNewId()    {        var sequencePart = GetSequenceValueForDateTime(DateTime.UtcNow); // extra check, just in case we manage to call GetNewId() twice before enough ticks have passed to increment the sequence         lock (Lock)        {            if (sequencePart <= _lastSequencePart)                sequencePart = _lastSequencePart + 1; _lastSequencePart = sequencePart;        } // shift so that the sequence part fills the most significant 6 bytes of the result value        sequencePart = (sequencePart << 16); // randomize the lowest 2 bytes of the result, just in case two different client PCs call GetNewId() at exactly the same time        var randomPart = Random.Next() & 0xFFFF; return sequencePart + randomPart;    } // used if you want to generate an Id value for a historic time point (within the start and end dates)    // there are no checks, compared to calls to GetNewId(), but the chances of colliding values are still almost zero    public static long GetIdForDateTime(DateTime dt)    {        if (dt < PeriodStartDate || dt > PeriodStartDate)            throw new ArgumentException($"value must be in the range {PeriodStartDate:dd MMM yyyy} - {PeriodEndDate:dd MMM yyyy}"); var sequencePart = GetSequenceValueForDateTime(dt.ToUniversalTime());        var randomPart = Random.Next() & 0xFFFF;        return ( sequencePart << 16 ) + randomPart;    } // Get a 6 byte sequence value from the specified date time - startDate => 0 --> endDate => 0x7FFFFFFFFFFF    // For a 100 year time period, 1 unit of the sequence corresponds to about 0.022 ms    private static long GetSequenceValueForDateTime(DateTime dt)    {        var ticksFromStart = dt.ToUniversalTime().Ticks - PeriodStartTicks;        var proportionOfPeriod = (decimal)ticksFromStart / TotalPeriodTicks;        var result = proportionOfPeriod * SEQUENCE_PART_PERMUTATIONS;        return (long)result;    } public static DateTime GetDateTimeForId(long value)    {        // strip off the random part - the two lowest bytes        var timePart = value >> 16;        var proportionOfTotalPeriod = (decimal) timePart / SEQUENCE_PART_PERMUTATIONS;        var ticks = (long)(proportionOfTotalPeriod * TotalPeriodTicks);        var result = PeriodStartDate.AddTicks(ticks);        return result;    }}