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

External references

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).