System.Guid — the built-in type
.NET uses System.Guid for 128-bit identifiers. No package needed — the full API is documented in the Microsoft Docs for System.Guid:
using System;
// Generate a random GUID (UUID v4 equivalent)
Guid id = Guid.NewGuid();
Console.WriteLine(id); // "550e8400-e29b-41d4-a716-446655440000"
// UUID v7 — time-sortable (.NET 9+)
Guid v7 = Guid.CreateVersion7();
Console.WriteLine(v7); // "018f3c4e-7a21-7b3c-9d4e-5f6a7b8c9d0e"
// Guid.Empty — the nil UUID (all zeros)
Console.WriteLine(Guid.Empty); // "00000000-0000-0000-0000-000000000000"
Guid.NewGuid() uses the platform CSPRNG (equivalent to crypto.randomUUID() in JS or uuid.uuid4() in Python). It is safe for all production uses.
Guid.CreateVersion7() — .NET 9+
.NET 9 added Guid.CreateVersion7() for time-sortable UUIDs:
// .NET 9+ — UUID v7 with current timestamp
Guid v7 = Guid.CreateVersion7();
// With a specific timestamp
Guid v7AtTime = Guid.CreateVersion7(DateTimeOffset.UtcNow.AddHours(-1));
Guid.CreateVersion7() embeds a millisecond timestamp in the high bits, so GUIDs sort chronologically. This is important for database performance — see UUID v4 vs UUID v7.
For earlier .NET versions (6, 7, 8), use the UUIDNext NuGet package:
dotnet add package UUIDNext
using UUIDNext;
Guid v7 = Uuid.NewSequential(); // UUID v7
Guid v4 = Uuid.NewRandom(); // UUID v4
Parsing and validating GUIDs
using System;
// Parse — throws FormatException on invalid input
Guid parsed = Guid.Parse("550e8400-e29b-41d4-a716-446655440000");
// Safe parse — returns false without throwing
if (Guid.TryParse("550e8400-e29b-41d4-a716-446655440000", out Guid result)) {
Console.WriteLine(result);
}
// Parse exact format — "D" = hyphenated (default)
Guid d = Guid.ParseExact("550e8400-e29b-41d4-a716-446655440000", "D");
// From a string at an API boundary
public static bool IsValidGuid(string s) =>
Guid.TryParse(s, out _);
Guid.TryParse accepts multiple formats: D (hyphenated, the standard), N (no hyphens), B (braces), P (parentheses).
String formats
Guid id = Guid.NewGuid();
id.ToString() // "550e8400-e29b-41d4-a716-446655440000" (default = "D")
id.ToString("D") // "550e8400-e29b-41d4-a716-446655440000" (hyphens)
id.ToString("N") // "550e8400e29b41d4a716446655440000" (no hyphens)
id.ToString("B") // "{550e8400-e29b-41d4-a716-446655440000}" (braces)
id.ToString("P") // "(550e8400-e29b-41d4-a716-446655440000)" (parentheses)
id.ToString("X") // "{0x550e8400,0xe29b,...}" (hex bytes)
Use "D" (the default) when interoperating with other languages and databases. RFC 9562 specifies lowercase as the canonical form — Guid.ToString() produces lowercase by default. GeeksforGeeks has a reference guide for System.Guid methods and format strings if you need a quick lookup.
Entity Framework Core
EF Core maps Guid primary keys automatically:
using System;
using Microsoft.EntityFrameworkCore;
public class Order
{
public Guid Id { get; set; } = Guid.NewGuid(); // v4 default
public string Status { get; set; } = string.Empty;
public decimal Amount { get; set; }
}
public class AppDbContext : DbContext
{
public DbSet<Order> Orders => Set<Order>();
protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Order>()
.HasKey(o => o.Id);
// Optional: tell EF Core the value is provided by the application
mb.Entity<Order>()
.Property(o => o.Id)
.ValueGeneratedNever();
}
}
For UUID v7 with EF Core (.NET 9+):
public class Order
{
// UUID v7 — time-sortable, better for database indexes
public Guid Id { get; set; } = Guid.CreateVersion7();
public string Status { get; set; } = string.Empty;
}
EF Core treats Guid as a uniqueidentifier in SQL Server and uuid in PostgreSQL. For PostgreSQL with Npgsql, Guid maps to the native uuid column type (16 bytes).
SQL Server byte-order caveat
SQL Server’s uniqueidentifier stores bytes in a mixed byte order (first 3 groups little-endian, last 2 groups big-endian). This means Guid.CreateVersion7() does not sort chronologically in SQL Server — the timestamp bytes land in the wrong positions after SQL Server’s internal reordering. The Wikipedia GUID article explains the historical reasons for this byte-order quirk, which dates to SQL Server’s COM origins.
-- SQL Server — use NEWSEQUENTIALID() for sequential GUIDs
CREATE TABLE orders (
id uniqueidentifier DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
status nvarchar(50) NOT NULL
);
For PostgreSQL, Guid.CreateVersion7() sorts correctly because PostgreSQL stores the uuid type in big-endian byte order matching the UUID v7 specification. See UUID vs GUID for the full explanation.
ASP.NET Core — UUID in routes and models
// Minimal API — Guid route parameter is validated automatically
app.MapGet("/orders/{id:guid}", (Guid id, OrderRepository repo) =>
repo.FindById(id) is Order order ? Results.Ok(order) : Results.NotFound()
);
// Model binding — Guid in request body (System.Text.Json)
public record CreateOrderRequest(string Status, decimal Amount);
app.MapPost("/orders", (CreateOrderRequest req, AppDbContext db) =>
{
var order = new Order
{
Id = Guid.CreateVersion7(), // time-sortable primary key
Status = req.Status,
Amount = req.Amount,
};
db.Orders.Add(order);
db.SaveChanges();
return Results.Created($"/orders/{order.Id}", order);
});
The :guid route constraint validates the format before the handler runs — invalid strings return 400 automatically.
Common mistakes
- Using
Guid.NewGuid()for database primary keys in high-volume tables.Guid.NewGuid()generates UUID v4 (random), which fragments B-tree indexes at scale. UseGuid.CreateVersion7()(.NET 9+) for database keys. - Comparing with
==on nullable Guid?. Use.Equals()or null-safe patterns —id?.Equals(other) == true. - SQL Server sort order. Don’t rely on
ORDER BY idwithuniqueidentifiercolumns being chronological — it won’t be with UUID v7 unless you apply a byte-swap. - Storing as
nvarchar(36)in SQL Server. Useuniqueidentifier(16 bytes). The string form wastes space and slows comparisons.
Related guides
- UUID vs GUID — why the same standard has two names
- UUID v4 vs UUID v7 — when to use Guid.NewGuid() vs Guid.CreateVersion7()
- UUID in databases — SQL Server, PostgreSQL storage
- UUID in .NET and C# — EF Core, SQL Server, and .NET 9 details
External references
- Microsoft Docs — System.Guid: official .NET API reference for Guid.NewGuid(), Guid.CreateVersion7(), Parse, and TryParse
- Wikipedia — Globally unique identifier: history of GUID, the Microsoft naming convention, and SQL Server byte-order details
- github.com/dorssel/uuidnext: UUIDNext — the NuGet package for UUID v7 on .NET 6, 7, and 8 before Guid.CreateVersion7()
- NuGet — UUIDNext: package page with download stats and version history for UUIDNext
- GeeksforGeeks — C# GUID: beginner guide to System.Guid in C# with code examples
- dev.to — UUID v7 in .NET 9: community article on Guid.CreateVersion7() and EF Core integration
- Medium — GUID vs UUID in .NET: deep-dive into System.Guid, byte order, and SQL Server uniqueidentifier behaviour
Frequently asked questions
What does Guid.NewGuid() return in C#?
Guid.NewGuid() returns a new random GUID (UUID v4 equivalent) using the operating system CSPRNG. The result is a System.Guid struct — a 16-byte value that prints in standard 8-4-4-4-12 format. For a time-sortable GUID (UUID v7), use Guid.CreateVersion7() in .NET 9+.
How do I generate UUID v7 in C#?
In .NET 9+, use Guid.CreateVersion7() from System — no package needed. For earlier .NET versions (6, 7, 8), install the UUIDNext NuGet package and use Uuid.NewSequential(). Note: UUID v7 does not sort correctly in SQL Server's uniqueidentifier type — use PostgreSQL for correct chronological ordering.
Does SQL Server use GUIDs or UUIDs?
SQL Server uses the term GUID and stores them in the uniqueidentifier column type (16 bytes). The values are compatible with standard UUIDs but SQL Server's internal byte order differs, which means UUID v7 does not sort chronologically as a uniqueidentifier without a byte-swap transformation.
How do I generate a GUID in C#?
Use Guid.NewGuid() from System — it generates a cryptographically secure UUID v4 equivalent. In .NET 9+, Guid.CreateVersion7() generates a time-sortable UUID v7. Both are in the System namespace with no extra packages needed.
What is Guid.NewGuid() in C#?
Guid.NewGuid() is a static method on System.Guid that generates a new random GUID (UUID v4 equivalent). It uses the operating system's cryptographically secure random number generator. The result is a 16-byte value formatted as a standard 8-4-4-4-12 UUID string.
How do I generate UUID v7 in C#?
Use Guid.CreateVersion7() in .NET 9+. This generates a time-sortable UUID v7 that sorts chronologically, which is better for database primary keys than Guid.NewGuid(). For earlier .NET versions, use the UUIDNext NuGet package.
Is a GUID the same as a UUID in C#?
Yes. C# uses the term GUID (Globally Unique Identifier) but System.Guid implements the same 128-bit UUID standard (RFC 9562). Guid.NewGuid() produces a UUID v4; Guid.CreateVersion7() produces a UUID v7. The values are interchangeable with UUID in other languages.
How do I use GUID as a primary key in Entity Framework Core?
Declare the Id property as Guid in your entity class. EF Core automatically generates a new Guid.NewGuid() value on insert. For UUID v7, configure a value generator or use .NET 9's Guid.CreateVersion7() as the default value factory.
How do I parse a GUID string in C#?
Use Guid.Parse(s) which throws FormatException on invalid input, or Guid.TryParse(s, out Guid result) which returns false without throwing. Both accept the standard hyphenated format and several other formats (no hyphens, braces, parentheses).