[{"data":1,"prerenderedAt":335},["ShallowReactive",2],{"topic-dotnet-entity-framework":3},{"framework":4,"topic":15,"subtopics":24},{"id":5,"description":6,"extension":7,"icon":8,"meta":9,"name":10,"order":11,"slug":8,"stem":12,"tier":13,"__hash__":14},"frameworks\u002Fframeworks\u002Fdotnet.yml",".NET Core interview questions on the CLR, C# language features, ASP.NET Core, dependency injection, Entity Framework, and deployment — the backbone of modern Microsoft-stack backend development.","yml","dotnet",{},".NET Core",7,"frameworks\u002Fdotnet",1,"_nP5kVwZOMUX9nd4gS5Ozj5Q6zQOEmGtLONE3ue01Gw",{"id":16,"description":17,"extension":7,"frameworkSlug":8,"meta":18,"name":19,"order":20,"slug":21,"stem":22,"__hash__":23},"topics\u002Ftopics\u002Fdotnet-entity-framework.yml","EF Core from the ground up — change tracking, migrations, LINQ-to-SQL translation, relationship configuration, and the performance traps that trip up most developers.",{},"Entity Framework Core",5,"entity-framework","topics\u002Fdotnet-entity-framework","gV3nrM57XFdlwpFXpSuGTWYCroc49eoYDH-ofJ-mvH0",[25,111,185,260],{"id":26,"title":27,"body":28,"description":32,"difficulty":35,"extension":36,"framework":10,"frameworkSlug":8,"meta":37,"navigation":38,"order":13,"path":39,"questions":40,"questionsCount":103,"related":104,"seo":105,"seoDescription":106,"stem":107,"subtopic":108,"topic":19,"topicSlug":21,"updated":109,"__hash__":110},"qa\u002Fdotnet\u002Fentity-framework\u002Fdbcontext-dbset.md","Dbcontext Dbset",{"type":29,"value":30,"toc":31},"minimark",[],{"title":32,"searchDepth":33,"depth":33,"links":34},"",2,[],"medium","md",{},true,"\u002Fdotnet\u002Fentity-framework\u002Fdbcontext-dbset",[41,46,50,54,58,62,66,70,74,78,82,86,90,94,99],{"id":42,"difficulty":43,"q":44,"a":45},"ef-dbcontext-role","easy","What is DbContext and what role does it play in EF Core?","**`DbContext`** is the primary entry point for EF Core. It combines three patterns:\n**Unit of Work** (batches changes), **Repository** (queries via `DbSet\u003CT>`), and\n**Identity Map** (tracks entity instances by primary key within the same scope).\n\n```csharp\n\u002F\u002F Define your context by deriving from DbContext:\npublic class AppDbContext : DbContext\n{\n    \u002F\u002F Each DbSet\u003CT> maps to a table — the query surface for that entity:\n    public DbSet\u003COrder>   Orders   { get; set; }\n    public DbSet\u003CProduct> Products { get; set; }\n    public DbSet\u003CCustomer> Customers { get; set; }\n\n    public AppDbContext(DbContextOptions\u003CAppDbContext> options)\n        : base(options) { }\n\n    protected override void OnModelCreating(ModelBuilder modelBuilder)\n    {\n        \u002F\u002F Fluent API configuration lives here:\n        modelBuilder.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);\n    }\n}\n\n\u002F\u002F Register in Program.cs — the container creates a new instance per request:\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options.UseSqlServer(builder.Configuration.GetConnectionString(\"Default\")));\n\n\u002F\u002F Inject and use in a service:\npublic class OrderService\n{\n    private readonly AppDbContext _db;\n    public OrderService(AppDbContext db) => _db = db;\n\n    public async Task\u003COrder?> GetOrderAsync(int id)\n        => await _db.Orders.FindAsync(id); \u002F\u002F uses identity map first\n}\n```\n\n**Rule of thumb:** `DbContext` is a scoped service — one instance per HTTP request.\nNever register it as Singleton; the change tracker is not thread-safe.\n",{"id":47,"difficulty":43,"q":48,"a":49},"ef-dbset-operations","What operations does DbSet\u003CT> expose and how do they map to SQL?","**`DbSet\u003CT>`** is the query and change surface for one entity type. LINQ methods\non it build SQL; add\u002Fremove\u002Fupdate methods stage changes in the change tracker.\n\n```csharp\n\u002F\u002F Querying — translated to SQL by EF Core's query pipeline:\nvar orders = await _db.Orders\n    .Where(o => o.CustomerId == customerId)   \u002F\u002F WHERE\n    .OrderByDescending(o => o.CreatedAt)      \u002F\u002F ORDER BY\n    .Take(20)                                  \u002F\u002F TOP 20\n    .ToListAsync();                            \u002F\u002F executes → SELECT\n\n\u002F\u002F Find by primary key (checks identity map before hitting DB):\nvar order = await _db.Orders.FindAsync(42);\n\n\u002F\u002F Staging changes — do NOT hit the DB until SaveChanges:\n_db.Orders.Add(new Order { CustomerId = 1 });    \u002F\u002F INSERT\n_db.Orders.Update(existingOrder);                \u002F\u002F UPDATE (all columns)\n_db.Orders.Remove(existingOrder);                \u002F\u002F DELETE\n\n\u002F\u002F SaveChanges wraps all staged ops in one transaction:\nawait _db.SaveChangesAsync();\n\n\u002F\u002F Direct SQL for non-LINQ operations:\nvar orders = await _db.Orders\n    .FromSqlRaw(\"SELECT * FROM Orders WHERE Status = {0}\", \"Pending\")\n    .ToListAsync();\n\n\u002F\u002F ExecuteSqlRawAsync for non-query statements (INSERT\u002FUPDATE\u002FDELETE):\nawait _db.Database.ExecuteSqlRawAsync(\n    \"DELETE FROM Orders WHERE CreatedAt \u003C {0}\", cutoff);\n```\n\n**Rule of thumb:** Use LINQ on `DbSet\u003CT>` for queries — EF translates it to\noptimised SQL. Fall back to `FromSqlRaw` or `ExecuteSqlRawAsync` only for\noperations LINQ can't express.\n",{"id":51,"difficulty":43,"q":52,"a":53},"ef-dbcontextoptions","How do you configure DbContextOptions and what provider options are available?","**`DbContextOptions\u003CTContext>`** carries the provider choice, connection string,\nand behaviour options. It's set during registration and injected into the context\nconstructor.\n\n```csharp\n\u002F\u002F SQL Server:\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options.UseSqlServer(\n        builder.Configuration.GetConnectionString(\"Default\"),\n        sql => sql.CommandTimeout(60)    \u002F\u002F per-query timeout in seconds\n                  .MigrationsAssembly(\"MyApp.Data\") \u002F\u002F separate assembly\n    ));\n\n\u002F\u002F SQLite (dev \u002F tests):\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options.UseSqlite(\"Data Source=app.db\"));\n\n\u002F\u002F PostgreSQL (Npgsql):\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options.UseNpgsql(connectionString));\n\n\u002F\u002F In-memory (tests only — not a real DB; no transactions or constraints):\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options.UseInMemoryDatabase(\"TestDb\"));\n\n\u002F\u002F Add diagnostics in development:\nif (builder.Environment.IsDevelopment())\n{\n    options.EnableSensitiveDataLogging(); \u002F\u002F shows param values in logs\n    options.EnableDetailedErrors();        \u002F\u002F richer error messages\n}\n\n\u002F\u002F Manual construction (e.g., in a factory):\nvar opts = new DbContextOptionsBuilder\u003CAppDbContext>()\n    .UseSqlServer(connectionString)\n    .Options;\n\nusing var db = new AppDbContext(opts);\n```\n\n**Rule of thumb:** Use `AddDbContext\u003CT>` for web apps — it handles lifetime and\ndisposal. Build `DbContextOptions` manually only in tests or migration tooling.\n",{"id":55,"difficulty":35,"q":56,"a":57},"ef-change-tracking","How does EF Core's change tracker work and what entity states are there?","The **change tracker** watches entity instances and records mutations so\n`SaveChanges` can generate the correct SQL without you specifying it.\n\n```csharp\n\u002F\u002F Entity states:\n\u002F\u002F Added    → INSERT on SaveChanges\n\u002F\u002F Modified → UPDATE on SaveChanges\n\u002F\u002F Deleted  → DELETE on SaveChanges\n\u002F\u002F Unchanged→ no SQL\n\u002F\u002F Detached → not tracked at all\n\nvar order = await _db.Orders.FindAsync(42); \u002F\u002F state: Unchanged\norder.Status = \"Shipped\";                   \u002F\u002F state: Modified (detected automatically)\nawait _db.SaveChangesAsync();               \u002F\u002F generates: UPDATE Orders SET Status=... WHERE Id=42\n\n\u002F\u002F Manual state management:\n_db.Entry(order).State = EntityState.Modified; \u002F\u002F mark all columns dirty\n_db.Entry(order).Property(o => o.Status).IsModified = true; \u002F\u002F only one column\n\n\u002F\u002F Inspect current state:\nConsole.WriteLine(_db.Entry(order).State); \u002F\u002F EntityState.Modified\n\n\u002F\u002F AsNoTracking — read-only queries; no change tracker overhead:\nvar orders = await _db.Orders\n    .AsNoTracking()\n    .Where(o => o.Status == \"Pending\")\n    .ToListAsync();\n\u002F\u002F Useful for read-heavy endpoints — faster, lower memory usage\n\n\u002F\u002F Attach a detached entity and mark it modified:\n_db.Orders.Attach(detachedOrder);\n_db.Entry(detachedOrder).State = EntityState.Modified;\nawait _db.SaveChangesAsync();\n```\n\n**Rule of thumb:** Use `AsNoTracking()` on read-only queries — it skips change\ntracker overhead and is measurably faster. Only track entities you intend to mutate.\n",{"id":59,"difficulty":35,"q":60,"a":61},"ef-savechanges","How does SaveChanges work and what happens under the hood?","**`SaveChanges`** \u002F **`SaveChangesAsync`** inspects the change tracker, generates\nSQL for every `Added`, `Modified`, and `Deleted` entity, and executes all of them\nin a **single implicit transaction**.\n\n```csharp\n\u002F\u002F Everything between two SaveChanges calls is one unit of work:\nvar customer = new Customer { Name = \"Alice\" };\n_db.Customers.Add(customer);                  \u002F\u002F queued: INSERT Customer\n\nvar product = await _db.Products.FindAsync(5);\nproduct.Stock -= 1;                            \u002F\u002F queued: UPDATE Product\n\nvar order = new Order { CustomerId = customer.Id, ProductId = 5 };\n_db.Orders.Add(order);                         \u002F\u002F queued: INSERT Order\n\n\u002F\u002F One round trip — all three ops in one transaction:\nint rows = await _db.SaveChangesAsync();       \u002F\u002F returns count of affected rows\n\n\u002F\u002F Manual transaction for multiple SaveChanges calls:\nawait using var tx = await _db.Database.BeginTransactionAsync();\ntry\n{\n    _db.Orders.Add(order);\n    await _db.SaveChangesAsync();          \u002F\u002F first save — inside tx\n\n    _db.Invoices.Add(invoice);\n    await _db.SaveChangesAsync();          \u002F\u002F second save — same tx\n\n    await tx.CommitAsync();\n}\ncatch\n{\n    await tx.RollbackAsync();\n    throw;\n}\n\n\u002F\u002F Intercept every save with SaveChangesInterceptor:\npublic class AuditInterceptor : SaveChangesInterceptor\n{\n    public override ValueTask\u003CInterceptionResult\u003Cint>> SavingChangesAsync(...)\n    {\n        foreach (var entry in context.ChangeTracker.Entries\u003CIAuditable>())\n            entry.Entity.UpdatedAt = DateTime.UtcNow; \u002F\u002F stamp before save\n        return base.SavingChangesAsync(...);\n    }\n}\n```\n\n**Rule of thumb:** Call `SaveChangesAsync` once per logical operation. Multiple\n`SaveChanges` calls in one request need an explicit transaction to stay atomic.\n",{"id":63,"difficulty":35,"q":64,"a":65},"ef-dbcontext-lifetime","Why should DbContext be registered as Scoped, not Singleton or Transient?","**`DbContext` is stateful** — the change tracker holds entity references tied to a\nspecific database connection. Registering it wrong causes data corruption or leaks.\n\n```csharp\n\u002F\u002F Scoped (correct) — one DbContext per HTTP request:\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options.UseSqlServer(connectionString));\n\u002F\u002F Default lifetime from AddDbContext is Scoped.\n\u002F\u002F Each request gets its own change tracker and connection.\n\n\u002F\u002F Singleton — DbContext shared across ALL requests concurrently:\n\u002F\u002F - Change tracker corrupted by overlapping requests.\n\u002F\u002F - Connection held open forever → exhausts the pool.\n\u002F\u002F - First writer's uncommitted data visible to other requests.\n\n\u002F\u002F Transient — new DbContext for every injection within a request:\n\u002F\u002F - An entity modified in ServiceA's context is NOT visible in ServiceB's context.\n\u002F\u002F - SaveChanges in ServiceA doesn't commit ServiceB's work.\n\u002F\u002F - Double the connection pool usage per request.\n\n\u002F\u002F Background services must create their own scope:\npublic class ReportWorker : BackgroundService\n{\n    private readonly IServiceScopeFactory _scopeFactory;\n    public ReportWorker(IServiceScopeFactory scopeFactory)\n        => _scopeFactory = scopeFactory;\n\n    protected override async Task ExecuteAsync(CancellationToken ct)\n    {\n        using var scope = _scopeFactory.CreateScope();\n        var db = scope.ServiceProvider.GetRequiredService\u003CAppDbContext>();\n        \u002F\u002F db is a fresh, properly scoped context for this job\n    }\n}\n```\n\n**Rule of thumb:** `DbContext` must be Scoped. Background services and singletons\nmust never inject it directly — use `IServiceScopeFactory` instead.\n",{"id":67,"difficulty":35,"q":68,"a":69},"ef-connection-pooling","What is DbContext pooling and when should you use it?","**`AddDbContextPool`** reuses `DbContext` instances from a pool rather than\ncreating a new one per request — removing the allocation and garbage collection\ncost per context (though EF Core resets the instance before reuse).\n\n```csharp\n\u002F\u002F Standard — creates a new AppDbContext per request:\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options.UseSqlServer(connectionString));\n\n\u002F\u002F Pooled — reuses instances from a pool (default size: 1024):\nbuilder.Services.AddDbContextPool\u003CAppDbContext>(options =>\n    options.UseSqlServer(connectionString),\n    poolSize: 128);        \u002F\u002F tune to expected concurrency\n\n\u002F\u002F Constraints with pooling:\n\u002F\u002F 1. AppDbContext constructor MUST accept only DbContextOptions — no extra injected deps.\n\u002F\u002F If you need IConfiguration, use the IDbContextFactory pattern instead.\n\u002F\u002F 2. OnConfiguring is called once, not per-request — configuration must be in options.\n\u002F\u002F 3. EF resets state (change tracker, transactions) but custom fields are NOT reset.\n\u002F\u002F Store no request-specific state in the context.\n\n\u002F\u002F IDbContextFactory — create short-lived contexts on demand (e.g. in Blazor Server):\nbuilder.Services.AddDbContextFactory\u003CAppDbContext>(options =>\n    options.UseSqlServer(connectionString));\n\npublic class ProductImporter\n{\n    private readonly IDbContextFactory\u003CAppDbContext> _factory;\n    public ProductImporter(IDbContextFactory\u003CAppDbContext> factory)\n        => _factory = factory;\n\n    public async Task ImportAsync(IEnumerable\u003CProduct> products)\n    {\n        await using var db = await _factory.CreateDbContextAsync();\n        db.Products.AddRange(products);\n        await db.SaveChangesAsync();\n    } \u002F\u002F context disposed here — safe in Blazor Server long-lived components\n}\n```\n\n**Rule of thumb:** Use `AddDbContextPool` for high-throughput APIs where context\ncreation is a measurable overhead. Use `IDbContextFactory` in Blazor Server or\nbackground jobs that need fine-grained context lifetime control.\n",{"id":71,"difficulty":35,"q":72,"a":73},"ef-onconfiguring-vs-adddbcontext","What is the difference between configuring EF Core via OnConfiguring vs AddDbContext?","**`OnConfiguring`** is the context's own method for self-configuring; **`AddDbContext`**\nconfigures externally via DI. The two approaches differ in testability and coupling.\n\n```csharp\n\u002F\u002F OnConfiguring — hardcodes provider; can't swap in tests:\npublic class AppDbContext : DbContext\n{\n    protected override void OnConfiguring(DbContextOptionsBuilder builder)\n    {\n        \u002F\u002F Connection string hardcoded; no way to inject a test database:\n        builder.UseSqlServer(\"Server=prod;Database=App;...\");\n    }\n}\n\n\u002F\u002F Constructor injection + AddDbContext (preferred):\npublic class AppDbContext : DbContext\n{\n    public AppDbContext(DbContextOptions\u003CAppDbContext> options)\n        : base(options) { }   \u002F\u002F options come from the DI container\n\n    protected override void OnModelCreating(ModelBuilder mb)\n    {\n        mb.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);\n    }\n}\n\n\u002F\u002F Wire-up in Program.cs — swap to SQLite in tests without changing the context:\nbuilder.Services.AddDbContext\u003CAppDbContext>(o =>\n    o.UseSqlServer(builder.Configuration.GetConnectionString(\"Default\")));\n\n\u002F\u002F Test setup:\nservices.AddDbContext\u003CAppDbContext>(o =>\n    o.UseSqlite(\"Data Source=:memory:\"));\n```\n\n`OnConfiguring` is only appropriate when the context is constructed manually\n(migration tooling, design-time factories).\n\n**Rule of thumb:** Never hardcode a connection string in `OnConfiguring` in\nproduction code. Pass `DbContextOptions` via the constructor so tests can inject\na different provider.\n",{"id":75,"difficulty":35,"q":76,"a":77},"ef-entity-configuration","How do you configure entity mappings in EF Core — data annotations vs Fluent API?","EF Core offers two mapping approaches: **data annotations** (attributes on the\nclass) and **Fluent API** (code in `OnModelCreating`). Fluent API is more powerful\nand keeps domain models free of infrastructure concerns.\n\n```csharp\n\u002F\u002F Data annotation approach — quick but pollutes the domain model:\n[Table(\"Orders\")]\npublic class Order\n{\n    [Key]\n    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]\n    public int Id { get; set; }\n\n    [Required]\n    [MaxLength(50)]\n    public string Status { get; set; } = \"\";\n\n    [Column(TypeName = \"decimal(18,2)\")]\n    public decimal Total { get; set; }\n}\n\n\u002F\u002F Fluent API approach — preferred; domain model stays clean:\npublic class OrderConfiguration : IEntityTypeConfiguration\u003COrder>\n{\n    public void Configure(EntityTypeBuilder\u003COrder> builder)\n    {\n        builder.ToTable(\"Orders\");\n        builder.HasKey(o => o.Id);\n        builder.Property(o => o.Status)\n               .IsRequired()\n               .HasMaxLength(50);\n        builder.Property(o => o.Total)\n               .HasColumnType(\"decimal(18,2)\");\n        builder.HasIndex(o => o.CustomerId); \u002F\u002F index on FK\n    }\n}\n\n\u002F\u002F Register all IEntityTypeConfiguration\u003CT> in one call:\nprotected override void OnModelCreating(ModelBuilder mb)\n    => mb.ApplyConfigurationsFromAssembly(typeof(AppDbContext).Assembly);\n```\n\n**Rule of thumb:** Use Fluent API via `IEntityTypeConfiguration\u003CT>` and\n`ApplyConfigurationsFromAssembly`. It scales to large models and keeps entity\nclasses free of EF-specific attributes.\n",{"id":79,"difficulty":35,"q":80,"a":81},"ef-value-conversions","What are value conversions in EF Core and when do you use them?","**Value conversions** let EF Core convert a property value between its in-memory\nCLR type and the database column type — useful for enums, strongly typed IDs,\nJSON columns, and encrypted fields.\n\n```csharp\n\u002F\u002F Store an enum as a string instead of an int:\npublic enum OrderStatus { Pending, Shipped, Delivered, Cancelled }\n\nbuilder.Property(o => o.Status)\n       .HasConversion\u003Cstring>()   \u002F\u002F stores \"Pending\", not 0\n       .HasMaxLength(20);\n\n\u002F\u002F Strongly typed ID value object:\npublic record OrderId(int Value);\n\nbuilder.Property(o => o.Id)\n       .HasConversion(\n           id => id.Value,        \u002F\u002F CLR → DB\n           val => new OrderId(val)); \u002F\u002F DB → CLR\n\n\u002F\u002F JSON column (EF Core 7+) — stores a complex type as JSON:\nbuilder.OwnsOne(o => o.ShippingAddress, addr =>\n{\n    addr.ToJson(); \u002F\u002F stored as a JSON column — one column, full object\n});\n\n\u002F\u002F Custom converter class:\npublic class MoneyConverter : ValueConverter\u003CMoney, decimal>\n{\n    public MoneyConverter() : base(\n        m => m.Amount,              \u002F\u002F CLR → DB\n        d => new Money(d, \"USD\"))   \u002F\u002F DB → CLR\n    { }\n}\n\nbuilder.Property(o => o.Price)\n       .HasConversion(new MoneyConverter());\n```\n\n**Rule of thumb:** Use value conversions to keep your domain model clean and\nstrongly typed. Store enums as strings for readability in production databases;\nstore value objects with `HasConversion` or `ToJson` rather than flattening manually.\n",{"id":83,"difficulty":35,"q":84,"a":85},"ef-global-query-filters","What are global query filters and how do you use them for soft deletes?","**Global query filters** apply a `WHERE` clause automatically to every query on\nan entity — the standard EF Core mechanism for **soft deletes** and **multi-tenancy**.\n\n```csharp\n\u002F\u002F Entity with soft-delete flag:\npublic class Order\n{\n    public int Id { get; set; }\n    public bool IsDeleted { get; set; }\n    public int TenantId { get; set; }\n    \u002F\u002F ...\n}\n\n\u002F\u002F Register global filter in OnModelCreating:\nmodelBuilder.Entity\u003COrder>()\n    .HasQueryFilter(o => !o.IsDeleted);\n\u002F\u002F Every query: SELECT * FROM Orders WHERE IsDeleted = 0 — automatic\n\n\u002F\u002F Multi-tenancy filter (inject the current tenant via constructor):\npublic class AppDbContext : DbContext\n{\n    private readonly int _tenantId;\n\n    public AppDbContext(DbContextOptions\u003CAppDbContext> opts, ITenantContext tenant)\n        : base(opts)\n    {\n        _tenantId = tenant.CurrentTenantId;\n    }\n\n    protected override void OnModelCreating(ModelBuilder mb)\n    {\n        mb.Entity\u003COrder>().HasQueryFilter(o =>\n            !o.IsDeleted && o.TenantId == _tenantId);\n    }\n}\n\n\u002F\u002F Bypass the filter when needed (admin operations, data migration):\nvar allOrders = await _db.Orders\n    .IgnoreQueryFilters()      \u002F\u002F disables global filters for this query\n    .ToListAsync();\n\n\u002F\u002F Soft delete — just set the flag, don't call Remove:\norder.IsDeleted = true;\nawait _db.SaveChangesAsync(); \u002F\u002F UPDATE Orders SET IsDeleted=1 WHERE Id=...\n```\n\n**Rule of thumb:** Use global query filters for cross-cutting concerns (soft delete,\nmulti-tenancy) so they're applied consistently. Add `IgnoreQueryFilters()` only in\nexplicit admin or migration paths.\n",{"id":87,"difficulty":35,"q":88,"a":89},"ef-keyless-entity-types","What are keyless entity types in EF Core and when do you use them?","**Keyless entity types** (`HasNoKey`) map to database objects that have no primary\nkey — database views, raw SQL result sets, or tables used only for reporting. They\nare always read-only; EF Core never tracks or saves them.\n\n```csharp\n\u002F\u002F DTO mapped to a view (no primary key):\npublic class OrderSummaryView\n{\n    public int CustomerId { get; set; }\n    public string CustomerName { get; set; } = \"\";\n    public int OrderCount { get; set; }\n    public decimal TotalRevenue { get; set; }\n}\n\n\u002F\u002F Configuration — mark as keyless and point to the view:\nmodelBuilder.Entity\u003COrderSummaryView>(b =>\n{\n    b.HasNoKey();                          \u002F\u002F no PK — never tracked\n    b.ToView(\"vw_OrderSummaries\");         \u002F\u002F maps to a DB view\n});\n\n\u002F\u002F Expose via a DbSet property on the context:\npublic DbSet\u003COrderSummaryView> OrderSummaries { get; set; }\n\n\u002F\u002F Query exactly like any DbSet — fully composable:\nvar top10 = await _db.OrderSummaries\n    .AsNoTracking()\n    .OrderByDescending(v => v.TotalRevenue)\n    .Take(10)\n    .ToListAsync();\n\u002F\u002F SQL: SELECT TOP 10 ... FROM vw_OrderSummaries ORDER BY TotalRevenue DESC\n\n\u002F\u002F Use FromSqlRaw with a keyless type for arbitrary result shapes:\nvar results = await _db.OrderSummaries\n    .FromSqlRaw(\"EXEC sp_GetOrderSummaries @Year = {0}\", 2026)\n    .ToListAsync();\n```\n\n**Rule of thumb:** Use keyless entity types for read-only views and stored procedure\nresults. Never call `SaveChanges` with them — EF has no way to generate INSERT\u002FUPDATE\u002F\nDELETE without a primary key.\n",{"id":91,"difficulty":35,"q":92,"a":93},"ef-raw-queries-ef8","What is SqlQuery and how does it differ from FromSqlRaw in EF Core 8?","**`SqlQuery\u003CT>`** (EF Core 8+) executes raw SQL and maps results to any CLR type —\nincluding primitives and non-entity types — without requiring a `DbSet\u003CT>` or keyless\nentity registration. `FromSqlRaw` only works with types known to the EF model.\n\n```csharp\n\u002F\u002F FromSqlRaw — requires the type to be in the EF model (entity or keyless):\nvar orders = await _db.Orders\n    .FromSqlRaw(\"SELECT * FROM Orders WHERE Status = {0}\", \"Pending\")\n    .ToListAsync(); \u002F\u002F Order must be a tracked or keyless type\n\n\u002F\u002F SqlQuery\u003CT> (EF Core 8+) — works with any scalar or simple CLR type:\n\n\u002F\u002F Scalar: fetch a single value:\nvar count = await _db.Database\n    .SqlQuery\u003Cint>($\"SELECT COUNT(*) FROM Orders WHERE Status = 'Pending'\")\n    .SingleAsync();\n\n\u002F\u002F Primitive list:\nvar ids = await _db.Database\n    .SqlQuery\u003Cint>($\"SELECT Id FROM Orders WHERE Total > {threshold}\")\n    .ToListAsync();\n\n\u002F\u002F Anonymous-like DTO (must be a concrete class with matching property names):\npublic record StatusCount(string Status, int Count);\n\nvar breakdown = await _db.Database\n    .SqlQuery\u003CStatusCount>(\n        $\"SELECT Status, COUNT(*) AS Count FROM Orders GROUP BY Status\")\n    .ToListAsync();\n\n\u002F\u002F Compose LINQ on top (EF wraps it in a subquery):\nvar top = await _db.Database\n    .SqlQuery\u003CStatusCount>(\n        $\"SELECT Status, COUNT(*) AS Count FROM Orders GROUP BY Status\")\n    .OrderByDescending(r => r.Count)\n    .Take(3)\n    .ToListAsync();\n```\n\n**Rule of thumb:** Use `SqlQuery\u003CT>` when you need raw SQL that returns scalars,\nprimitives, or ad-hoc DTOs not registered in the EF model. Use `FromSqlRaw` when\nyou want to compose LINQ on top of a raw SQL fragment that returns a tracked entity type.\n",{"id":95,"difficulty":96,"q":97,"a":98},"ef-interceptors","hard","What are EF Core interceptors and how do you use them for auditing?","**Interceptors** hook into EF Core's internal pipeline at specific points — command\nexecution, connection events, and SaveChanges — without modifying entity classes.\n\n```csharp\n\u002F\u002F Auditing interceptor — stamp UpdatedAt before every save:\npublic class AuditInterceptor : SaveChangesInterceptor\n{\n    public override InterceptionResult\u003Cint> SavingChanges(\n        DbContextEventData eventData, InterceptionResult\u003Cint> result)\n    {\n        StampAuditFields(eventData.Context!);\n        return base.SavingChanges(eventData, result);\n    }\n\n    public override ValueTask\u003CInterceptionResult\u003Cint>> SavingChangesAsync(\n        DbContextEventData eventData, InterceptionResult\u003Cint> result,\n        CancellationToken ct = default)\n    {\n        StampAuditFields(eventData.Context!);\n        return base.SavingChangesAsync(eventData, result, ct);\n    }\n\n    private static void StampAuditFields(DbContext db)\n    {\n        var now = DateTime.UtcNow;\n        foreach (var entry in db.ChangeTracker.Entries\u003CIAuditable>())\n        {\n            if (entry.State == EntityState.Added)\n                entry.Entity.CreatedAt = now;\n            if (entry.State is EntityState.Added or EntityState.Modified)\n                entry.Entity.UpdatedAt = now;\n        }\n    }\n}\n\n\u002F\u002F Command interceptor — log slow queries:\npublic class SlowQueryInterceptor : DbCommandInterceptor\n{\n    public override DbDataReader ReaderExecuted(\n        DbCommand command, CommandExecutedEventData data, DbDataReader result)\n    {\n        if (data.Duration > TimeSpan.FromSeconds(1))\n            Console.WriteLine($\"SLOW QUERY ({data.Duration.TotalMs}ms): {command.CommandText}\");\n        return result;\n    }\n}\n\n\u002F\u002F Register interceptors on the context:\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options\n        .UseSqlServer(connectionString)\n        .AddInterceptors(new AuditInterceptor(), new SlowQueryInterceptor()));\n```\n\n**Rule of thumb:** Use interceptors for cross-cutting concerns (auditing, logging,\nsoft-delete) that shouldn't pollute entity classes or service code. Prefer\n`SaveChangesInterceptor` over overriding `SaveChanges` directly — it composes cleanly.\n",{"id":100,"difficulty":96,"q":101,"a":102},"ef-unit-of-work-repository","Should you wrap EF Core DbContext in a Repository and Unit of Work pattern?","`DbContext` already implements the **Unit of Work** pattern (change tracker + `SaveChanges`)\nand `DbSet\u003CT>` already acts as a **Repository** (query + add\u002Fremove surface). Wrapping\nthem in another layer duplicates those abstractions. However, a thin repository interface\ncan be justified for testability or for abstracting query logic.\n\n```csharp\n\u002F\u002F Anti-pattern — generic repository that mirrors DbSet exactly:\npublic interface IRepository\u003CT>\n{\n    Task\u003CT?> GetByIdAsync(int id);\n    Task AddAsync(T entity);\n    void Remove(T entity);\n    Task SaveAsync(); \u002F\u002F re-exposes SaveChanges — leaks UoW into the repo\n}\n\u002F\u002F Problem: SaveAsync in each repository breaks the Unit of Work contract.\n\u002F\u002F Two repos saving independently means two transactions.\n\n\u002F\u002F Better — inject DbContext directly in services (simple apps):\npublic class OrderService\n{\n    private readonly AppDbContext _db;\n    public OrderService(AppDbContext db) => _db = db;\n\n    public async Task\u003CList\u003COrder>> GetPendingAsync()\n        => await _db.Orders\n            .AsNoTracking()\n            .Where(o => o.Status == \"Pending\")\n            .ToListAsync();\n}\n\n\u002F\u002F Acceptable thin interface — encapsulates query logic, not UoW:\npublic interface IOrderRepository\n{\n    Task\u003CList\u003COrder>> GetPendingAsync(CancellationToken ct = default);\n    Task\u003COrder?> GetWithItemsAsync(int orderId, CancellationToken ct = default);\n}\n\npublic class EfOrderRepository : IOrderRepository\n{\n    private readonly AppDbContext _db;\n    public EfOrderRepository(AppDbContext db) => _db = db;\n\n    public Task\u003CList\u003COrder>> GetPendingAsync(CancellationToken ct)\n        => _db.Orders.AsNoTracking().Where(o => o.Status == \"Pending\").ToListAsync(ct);\n\n    public Task\u003COrder?> GetWithItemsAsync(int orderId, CancellationToken ct)\n        => _db.Orders.Include(o => o.Items).FirstOrDefaultAsync(o => o.Id == orderId, ct);\n}\n\u002F\u002F SaveChanges remains on the context — owned by the service layer, not the repo.\n```\n\n**Rule of thumb:** Don't create a generic `IRepository\u003CT>` that wraps `DbSet\u003CT>` —\nit adds indirection without benefit. A domain-specific repository interface is fine when\nit encapsulates complex queries. Never expose `SaveChanges` inside a repository method.\n",15,null,{"description":32},"EF Core DbContext interview questions — change tracking, entity states, SaveChanges, lifetime management, DbContext pooling, and interceptors.","dotnet\u002Fentity-framework\u002Fdbcontext-dbset","DbContext & DbSet","2026-06-23","VQ5zE74TIo4nHgSY65q7FMINMkZmGjJajlkcPsfpCjI",{"id":112,"title":113,"body":114,"description":32,"difficulty":35,"extension":36,"framework":10,"frameworkSlug":8,"meta":118,"navigation":38,"order":33,"path":119,"questions":120,"questionsCount":103,"related":104,"seo":181,"seoDescription":182,"stem":183,"subtopic":113,"topic":19,"topicSlug":21,"updated":109,"__hash__":184},"qa\u002Fdotnet\u002Fentity-framework\u002Fmigrations.md","Migrations",{"type":29,"value":115,"toc":116},[],{"title":32,"searchDepth":33,"depth":33,"links":117},[],{},"\u002Fdotnet\u002Fentity-framework\u002Fmigrations",[121,125,129,133,137,141,145,149,153,157,161,165,169,173,177],{"id":122,"difficulty":43,"q":123,"a":124},"ef-migrations-what","What are EF Core migrations and why do you use them instead of manual schema scripts?","**EF Core migrations** are versioned C# classes that translate model changes into\ndatabase schema operations. Each migration has an `Up` (apply) and a `Down` (revert)\nmethod, making schema evolution repeatable and reversible.\n\n```csharp\n\u002F\u002F 1. Add a migration after changing the model:\n\u002F\u002F dotnet ef migrations add AddOrderStatusColumn\n\n\u002F\u002F Generated migration file:\npublic partial class AddOrderStatusColumn : Migration\n{\n    protected override void Up(MigrationBuilder migrationBuilder)\n    {\n        migrationBuilder.AddColumn\u003Cstring>(\n            name: \"Status\",\n            table: \"Orders\",\n            type: \"nvarchar(50)\",\n            nullable: false,\n            defaultValue: \"Pending\");\n\n        migrationBuilder.CreateIndex(\n            name: \"IX_Orders_Status\",\n            table: \"Orders\",\n            column: \"Status\");\n    }\n\n    protected override void Down(MigrationBuilder migrationBuilder)\n    {\n        migrationBuilder.DropIndex(\"IX_Orders_Status\", \"Orders\");\n        migrationBuilder.DropColumn(\"Status\", \"Orders\");\n    }\n}\n\n\u002F\u002F 2. Apply to the database:\n\u002F\u002F dotnet ef database update\n\u002F\u002F Or programmatically at startup:\nawait db.Database.MigrateAsync(); \u002F\u002F applies all pending migrations\n```\n\nBenefits over manual scripts: migrations are source-controlled, tied to the model,\nreversible with `Down`, and apply in order via the `__EFMigrationsHistory` table.\n\n**Rule of thumb:** One migration per logical schema change. Never edit a migration\nonce it's been applied to any shared environment — add a new migration instead.\n",{"id":126,"difficulty":43,"q":127,"a":128},"ef-migrations-workflow","What is the standard EF Core migration workflow from model change to production?","The migration workflow moves schema changes through dev → CI → staging → prod in\na controlled, repeatable way.\n\n```bash\n# 1. Change the model (add property, new entity, new relationship)\n\n# 2. Generate the migration:\ndotnet ef migrations add \u003CMigrationName> --project MyApp.Data --startup-project MyApp.Api\n\n# 3. Review the generated migration file — always inspect Up\u002FDown before committing:\n#    migrations\u002F\u003Ctimestamp>_\u003CMigrationName>.cs\n\n# 4. Apply to local dev DB:\ndotnet ef database update\n\n# 5. Commit migration files alongside the model change — one PR, both together.\n\n# 6. Apply in CI (integration tests run against a real migrated DB):\n#    services.AddDbContext\u003CAppDbContext>(...);\n#    db.Database.Migrate(); \u002F\u002F in test fixture setup\n\n# 7. Apply to staging and production — never dotnet ef in prod:\n#    Option A: db.Database.MigrateAsync() in app startup (simple, single-server)\n#    Option B: migration bundle (preferred for containerised deployments):\ndotnet ef migrations bundle --self-contained -o migrate\n# Then run: .\u002Fmigrate --connection \"...\"\n```\n\n```csharp\n\u002F\u002F Programmatic startup migration (option A):\nvar app = builder.Build();\n\nusing (var scope = app.Services.CreateScope())\n{\n    var db = scope.ServiceProvider.GetRequiredService\u003CAppDbContext>();\n    await db.Database.MigrateAsync(); \u002F\u002F idempotent — skips applied migrations\n}\n\nawait app.RunAsync();\n```\n\n**Rule of thumb:** Always commit migration files with the model change. Never apply\n`dotnet ef database update` directly to production — use `MigrateAsync` at startup\nor a migration bundle in a deploy step.\n",{"id":130,"difficulty":43,"q":131,"a":132},"ef-migrations-history","What is the __EFMigrationsHistory table and how does EF Core use it?","**`__EFMigrationsHistory`** is a bookkeeping table EF Core creates and maintains.\nIt records every applied migration by name and the EF Core product version, giving\n`MigrateAsync` its idempotency.\n\n```sql\n-- Created automatically by EF Core; looks like:\nCREATE TABLE __EFMigrationsHistory (\n    MigrationId     nvarchar(150) NOT NULL,\n    ProductVersion  nvarchar(32)  NOT NULL,\n    CONSTRAINT PK___EFMigrationsHistory PRIMARY KEY (MigrationId)\n);\n\n-- After applying two migrations, the table contains:\n-- | MigrationId                            | ProductVersion |\n-- | 20240101000000_InitialCreate            | 8.0.0          |\n-- | 20240615120000_AddOrderStatusColumn     | 8.0.0          |\n```\n\n```csharp\n\u002F\u002F Check pending migrations programmatically:\nvar pending = await db.Database.GetPendingMigrationsAsync();\nConsole.WriteLine($\"{pending.Count()} migration(s) pending\");\n\n\u002F\u002F List applied migrations:\nvar applied = await db.Database.GetAppliedMigrationsAsync();\n\n\u002F\u002F Remove a migration that hasn't been applied yet (resets the snapshot):\n\u002F\u002F dotnet ef migrations remove\n\n\u002F\u002F \"Fake\" applying a migration (schema already exists but EF doesn't know):\n\u002F\u002F dotnet ef database update --target MigrationName\n\u002F\u002F Then manually insert a row into __EFMigrationsHistory.\n```\n\n**Rule of thumb:** Never edit `__EFMigrationsHistory` manually in production unless\nyou are recovering from a partial failed migration. If a migration fails mid-run, fix\nthe migration and rerun — don't delete the history row.\n",{"id":134,"difficulty":43,"q":135,"a":136},"ef-data-seeding","How do you seed data with EF Core migrations?","EF Core provides **model-based seeding** via `HasData` in `OnModelCreating` for\nstatic reference data, and **custom seeding** code for dynamic or environment-specific\ndata.\n\n```csharp\n\u002F\u002F Model-based seeding — becomes part of the migration:\nprotected override void OnModelCreating(ModelBuilder mb)\n{\n    mb.Entity\u003CCategory>().HasData(\n        new Category { Id = 1, Name = \"Electronics\", Slug = \"electronics\" },\n        new Category { Id = 2, Name = \"Clothing\",    Slug = \"clothing\"    },\n        new Category { Id = 3, Name = \"Books\",       Slug = \"books\"       }\n    );\n}\n\u002F\u002F dotnet ef migrations add SeedCategories generates an InsertData migration.\n\u002F\u002F EF Core tracks these rows — updating HasData generates an UpdateData migration.\n\u002F\u002F Primary keys must be set explicitly (no DB-generated keys for seed data).\n\n\u002F\u002F Custom startup seeding — for dynamic data not tracked by migrations:\npublic static class DatabaseSeeder\n{\n    public static async Task SeedAsync(AppDbContext db)\n    {\n        if (await db.Users.AnyAsync(u => u.Email == \"admin@example.com\"))\n            return; \u002F\u002F idempotent — skip if already seeded\n\n        db.Users.Add(new User\n        {\n            Email    = \"admin@example.com\",\n            Role     = \"Admin\",\n            Password = PasswordHasher.Hash(\"change-me-on-first-login\")\n        });\n\n        await db.SaveChangesAsync();\n    }\n}\n\n\u002F\u002F Call after MigrateAsync at startup:\nawait db.Database.MigrateAsync();\nawait DatabaseSeeder.SeedAsync(db);\n```\n\n**Rule of thumb:** Use `HasData` only for static reference data with stable IDs\n(lookup tables, role definitions). Use custom seeder code for admin users, test data,\nor anything that varies by environment.\n",{"id":138,"difficulty":35,"q":139,"a":140},"ef-design-time-factory","What is a design-time DbContext factory and when do you need one?","A **design-time factory** (`IDesignTimeDbContextFactory\u003CT>`) tells EF migration\ntooling how to construct the `DbContext` when the startup project can't be used\nas-is — for example when the context is in a separate class library.\n\n```csharp\n\u002F\u002F Required when:\n\u002F\u002F - AppDbContext lives in a class library (no Program.cs to discover)\n\u002F\u002F - Context constructor needs non-DI arguments at design time\n\u002F\u002F - Connection string differs between design time and runtime\n\npublic class AppDbContextFactory : IDesignTimeDbContextFactory\u003CAppDbContext>\n{\n    public AppDbContext CreateDbContext(string[] args)\n    {\n        \u002F\u002F Read config from appsettings.json at design time:\n        var config = new ConfigurationBuilder()\n            .SetBasePath(Directory.GetCurrentDirectory())\n            .AddJsonFile(\"appsettings.json\")\n            .AddEnvironmentVariables()\n            .Build();\n\n        var options = new DbContextOptionsBuilder\u003CAppDbContext>()\n            .UseSqlServer(config.GetConnectionString(\"Default\"))\n            .Options;\n\n        return new AppDbContext(options);\n    }\n}\n```\n\nEF tooling (`dotnet ef migrations add`, `dotnet ef database update`) automatically\ndiscovers `IDesignTimeDbContextFactory\u003CT>` implementations at design time.\n\n```bash\n# Specify both projects when context is in a library:\ndotnet ef migrations add InitialCreate \\\n    --project MyApp.Data \\          # where DbContext lives\n    --startup-project MyApp.Api      # where appsettings.json lives\n```\n\n**Rule of thumb:** Always create a design-time factory when `AppDbContext` is in a\nclass library. Without it, `dotnet ef` either fails or picks the wrong connection string.\n",{"id":142,"difficulty":35,"q":143,"a":144},"ef-migration-bundles","What are EF Core migration bundles and why are they preferred for CI\u002FCD?","**Migration bundles** are standalone executables that apply pending migrations — no\n.NET SDK or EF CLI required at deploy time. They are the production-safe alternative\nto running `dotnet ef database update` in a pipeline.\n\n```bash\n# Build a self-contained migration bundle:\ndotnet ef migrations bundle \\\n    --self-contained \\\n    --runtime linux-x64 \\\n    -o .\u002Fmigrate \\\n    --project MyApp.Data \\\n    --startup-project MyApp.Api\n\n# This produces a single binary: .\u002Fmigrate\n\n# Run in CI\u002FCD or Kubernetes init container:\n.\u002Fmigrate --connection \"Server=prod;Database=App;User=sa;Password=...\"\n\n# Flags:\n# --target \u003CMigrationName>   — migrate to a specific version (rollback)\n# --no-transactions          — disable wrapping each migration in a transaction\n# --verbose                  — show individual SQL statements\n```\n\n```yaml\n# Kubernetes — init container applies migrations before the app starts:\ninitContainers:\n  - name: db-migrate\n    image: myapp-migrate:latest  # contains the bundle\n    command: [\".\u002Fmigrate\"]\n    env:\n      - name: ConnectionStrings__Default\n        valueFrom:\n          secretKeyRef:\n            name: db-secret\n            key: connection-string\n```\n\n**Rule of thumb:** Build a migration bundle as part of CI and run it in an init\ncontainer or deploy step — never auto-migrate inside the application process\nin a multi-replica deployment (races between replicas).\n",{"id":146,"difficulty":35,"q":147,"a":148},"ef-rollback","How do you roll back a migration in EF Core?","EF Core supports targeted rollback via `dotnet ef database update \u003Ctarget>`, which\ncalls each migration's `Down` method in reverse order.\n\n```bash\n# List all migrations (applied and pending):\ndotnet ef migrations list\n\n# Roll back to a specific migration (exclusive — that migration stays applied):\ndotnet ef database update AddOrderStatusColumn\n\n# Roll back ALL migrations (empty database — __EFMigrationsHistory stays):\ndotnet ef database update 0\n\n# Remove the last migration that hasn't been applied to any shared DB:\ndotnet ef migrations remove\n# Rewrites the model snapshot — only safe if the migration hasn't been shared.\n```\n\n```csharp\n\u002F\u002F Programmatic rollback (useful in integration tests):\nawait db.Database.MigrateAsync();  \u002F\u002F apply up to latest\n\n\u002F\u002F Or target a specific migration in a test fixture:\nawait db.GetService\u003CIMigrator>()\n        .MigrateAsync(\"20240101000000_InitialCreate\"); \u002F\u002F migrate to this point\n```\n\nProduction rollback considerations:\n- `Down` methods must be written carefully — data loss is possible (e.g., `DropColumn`).\n- For zero-downtime deploys, prefer **forward-only** migrations (never auto-populate `Down`).\n- Always back up the database before rolling back in production.\n\n**Rule of thumb:** Write `Down` methods when the migration is purely structural (indexes,\ncolumn renames). For migrations that delete columns or tables, leave `Down` empty and add\na forward migration to recover — never roll back data loss in production.\n",{"id":150,"difficulty":35,"q":151,"a":152},"ef-migration-squashing","How do you squash or consolidate many EF Core migrations?","As migrations accumulate, startup time and migration history grow. **Squashing**\nreplaces many small migrations with a single baseline migration.\n\n```bash\n# 1. Ensure all team environments are up to date with latest migration.\n\n# 2. Delete all existing migration files:\nrm Migrations\u002F*.cs   # keep only the Designer snapshot\n\n# 3. Create a new baseline migration from the current model snapshot:\ndotnet ef migrations add Baseline --ignore-changes\n# --ignore-changes: generates a migration without diffing (uses the current model)\n\n# 4. Mark the new migration as already applied on existing databases:\nINSERT INTO __EFMigrationsHistory (MigrationId, ProductVersion)\nVALUES ('20260101000000_Baseline', '8.0.0');\n# Then delete all previous rows from the table.\n\n# 5. Fresh databases get the Baseline migration applied normally.\n```\n\n```csharp\n\u002F\u002F Alternative: EnsureCreated for dev\u002Ftest (no migrations at all):\nawait db.Database.EnsureCreatedAsync();\n\u002F\u002F Creates schema from the current model snapshot — no migration history.\n\u002F\u002F Useful in tests; NOT a replacement for migrations in production.\n```\n\n**Rule of thumb:** Squash migrations when the history is unwieldy (50+ migrations)\nOR when you want a clean baseline after a major refactor. Coordinate with all\nenvironments before squashing — every DB must be at the latest migration first.\n",{"id":154,"difficulty":35,"q":155,"a":156},"ef-generated-sql","How do you inspect the SQL that EF Core migration commands generate?","EF Core provides several ways to preview SQL before applying it — critical for\ncatching unexpected schema changes in production.\n\n```bash\n# Script the migration instead of applying it:\ndotnet ef migrations script                    # all migrations → SQL file\ndotnet ef migrations script FromMigration ToMigration  # range\n\n# Idempotent script (safe to run multiple times):\ndotnet ef migrations script --idempotent\n# Wraps each migration in IF NOT EXISTS checks against __EFMigrationsHistory\n\n# Preview what update would do (no DB changes):\ndotnet ef database update --dry-run           # prints SQL, doesn't execute\n```\n\n```csharp\n\u002F\u002F Log all generated SQL at runtime via EF Core logging:\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options\n        .UseSqlServer(connectionString)\n        .LogTo(Console.WriteLine, LogLevel.Information)    \u002F\u002F all EF logs\n        .EnableSensitiveDataLogging());                    \u002F\u002F include param values\n\n\u002F\u002F Or capture in a StringBuilder for tests:\nvar log = new StringBuilder();\noptions.LogTo(msg => log.AppendLine(msg), LogLevel.Information);\n```\n\n**Rule of thumb:** Always run `dotnet ef migrations script --idempotent` in CI\nand review the output before applying to staging or production. Never apply a\nmigration you haven't read.\n",{"id":158,"difficulty":35,"q":159,"a":160},"ef-multiple-dbcontexts","How do you manage multiple DbContexts in one application?","Some applications split concerns across multiple `DbContext` types — for example,\nseparate contexts for the main domain and for identity management. Each needs its\nown migration history table.\n\n```csharp\n\u002F\u002F Two separate contexts — each with its own schema area:\npublic class AppDbContext : DbContext\n{\n    public DbSet\u003COrder> Orders { get; set; }\n    public DbSet\u003CProduct> Products { get; set; }\n}\n\npublic class IdentityDbContext : IdentityDbContext\u003CApplicationUser>\n{\n    \u002F\u002F ASP.NET Core Identity tables (AspNetUsers, AspNetRoles, etc.)\n}\n\n\u002F\u002F Register both:\nbuilder.Services.AddDbContext\u003CAppDbContext>(o =>\n    o.UseSqlServer(connectionString));\n\nbuilder.Services.AddDbContext\u003CIdentityDbContext>(o =>\n    o.UseSqlServer(connectionString));\n\n\u002F\u002F Separate migration history tables to avoid conflicts:\nprotected override void OnModelCreating(ModelBuilder mb)\n{\n    mb.HasDefaultSchema(\"identity\"); \u002F\u002F or use MigrationsHistoryTable\n}\n\n\u002F\u002F Or configure explicitly:\noptions.UseSqlServer(conn, sql =>\n    sql.MigrationsHistoryTable(\"__IdentityMigrationsHistory\", \"identity\"));\n```\n\n```bash\n# Run migrations per context:\ndotnet ef migrations add InitialCreate --context AppDbContext\ndotnet ef migrations add IdentityInit   --context IdentityDbContext\n\ndotnet ef database update --context AppDbContext\ndotnet ef database update --context IdentityDbContext\n```\n\n**Rule of thumb:** Use separate `DbContext` types for bounded contexts or separate\ninfrastructure concerns (identity, tenancy, auditing). Always configure distinct\n`MigrationsHistoryTable` names to prevent migration conflicts.\n",{"id":162,"difficulty":43,"q":163,"a":164},"ef-ensure-created-vs-migrate","What is the difference between EnsureCreated and MigrateAsync?","**`EnsureCreated`** creates the database schema from the current EF model snapshot in\none step — no migration files involved. **`MigrateAsync`** applies versioned migration\nfiles in order and records them in `__EFMigrationsHistory`.\n\n```csharp\n\u002F\u002F EnsureCreated — creates schema if the DB doesn't exist; no-op if it does:\nawait db.Database.EnsureCreatedAsync();\n\u002F\u002F Good for: unit\u002Fintegration tests, quick prototyping, in-memory database\n\u002F\u002F Bad for: production — bypasses migrations; EF can't diff or evolve the schema later\n\n\u002F\u002F MigrateAsync — applies all pending migrations in order; idempotent:\nawait db.Database.MigrateAsync();\n\u002F\u002F Good for: production, staging, CI — schema is versioned and repeatable\n\u002F\u002F Requires migration files to exist first (dotnet ef migrations add)\n\n\u002F\u002F Critical incompatibility:\n\u002F\u002F If you call EnsureCreated on a database, then later switch to migrations,\n\u002F\u002F MigrateAsync fails — the schema exists but __EFMigrationsHistory is empty.\n\u002F\u002F EF thinks migrations haven't been applied and tries to re-create tables → error.\n\n\u002F\u002F Test setup pattern — EnsureCreated is fine because tests always start fresh:\npublic class TestFixture : IAsyncLifetime\n{\n    private readonly AppDbContext _db;\n\n    public async Task InitializeAsync()\n    {\n        await _db.Database.EnsureDeletedAsync(); \u002F\u002F clean slate\n        await _db.Database.EnsureCreatedAsync(); \u002F\u002F schema from model snapshot\n    }\n\n    public async Task DisposeAsync()\n        => await _db.Database.EnsureDeletedAsync();\n}\n```\n\n**Rule of thumb:** Use `EnsureCreated` only in tests or demos with an in-memory or\nSQLite database. Use `MigrateAsync` everywhere else — it's the only approach that\nsupports schema evolution without data loss.\n",{"id":166,"difficulty":96,"q":167,"a":168},"ef-pending-model-changes","How do you detect and prevent model\u002Fmigration drift in CI?","**Model\u002Fmigration drift** occurs when the model changes but no migration is added,\nmeaning the deployed schema won't match the running code. Detecting this in CI\nprevents production failures.\n\n```bash\n# EF Core 8+ — dotnet ef migrations has-pending-model-changes exits non-zero\n# if the model snapshot differs from the current model (no migration was generated):\ndotnet ef migrations has-pending-model-changes \\\n    --project MyApp.Data \\\n    --startup-project MyApp.Api\n\n# CI step (GitHub Actions \u002F bash):\nif ! dotnet ef migrations has-pending-model-changes ...; then\n    echo \"ERROR: Model changed without a migration. Run 'dotnet ef migrations add'.\"\n    exit 1\nfi\n```\n\n```csharp\n\u002F\u002F At startup — warn if any migration is pending (alternative CI check):\nvar pending = await db.Database.GetPendingMigrationsAsync();\nif (pending.Any())\n    throw new InvalidOperationException(\n        $\"Database has {pending.Count()} pending migration(s). Run MigrateAsync or apply the bundle.\");\n\n\u002F\u002F Integration test guard:\n[Fact]\npublic void NoUnappliedMigrations()\n{\n    using var db = CreateTestContext();\n    db.Database.Migrate();\n    var pending = db.Database.GetPendingMigrations();\n    Assert.Empty(pending);\n}\n```\n\n**Rule of thumb:** Add `dotnet ef migrations has-pending-model-changes` as a CI step.\nGate merges on a clean result — a model change without a migration is a production outage\nwaiting to happen.\n",{"id":170,"difficulty":35,"q":171,"a":172},"ef-migrations-transactions","Are EF Core migrations applied inside a database transaction?","By default, each migration's `Up` method runs inside its own **database transaction**,\nso a failing migration is rolled back cleanly. However, some DDL statements are\nnon-transactional on certain databases (SQL Server: `CREATE DATABASE`, `ALTER DATABASE`;\nPostgreSQL: certain index operations).\n\n```csharp\n\u002F\u002F Default behaviour — each migration is wrapped automatically:\npublic partial class AddOrderStatusColumn : Migration\n{\n    \u002F\u002F EF Core wraps this Up() in a transaction unless you suppress it:\n    protected override void Up(MigrationBuilder migrationBuilder)\n    {\n        migrationBuilder.AddColumn\u003Cstring>(\n            name: \"Status\",\n            table: \"Orders\",\n            type: \"nvarchar(50)\",\n            nullable: false,\n            defaultValue: \"Pending\");\n    }\n\n    \u002F\u002F Opt out of the transaction for this migration (e.g., CREATE INDEX CONCURRENTLY on Postgres):\n    protected override void Up(MigrationBuilder migrationBuilder)\n    {\n        migrationBuilder.Sql(\n            \"CREATE INDEX CONCURRENTLY IX_Orders_Status ON Orders(Status);\",\n            suppressTransaction: true); \u002F\u002F run outside a transaction\n    }\n}\n\n\u002F\u002F Apply without wrapping migrations in transactions (bundle flag):\n\u002F\u002F .\u002Fmigrate --no-transactions\n\n\u002F\u002F Manual transaction via MigrationBuilder.BeginTransaction is not available —\n\u002F\u002F the framework controls the transaction boundary. Use suppressTransaction: true\n\u002F\u002F only for statements that cannot run inside a transaction.\n```\n\nPartial migration failure in production:\n- If the migration throws after some statements but inside the EF transaction, the DB is rolled back.\n- If `suppressTransaction: true` statements fail, the DB is left in a partial state — you must fix\n  and rerun manually. Always script `--idempotent` SQL before running these.\n\n**Rule of thumb:** Rely on EF's default transaction wrapping. Use `suppressTransaction: true`\nonly for database-specific statements that explicitly forbid transactions. Test those migrations\non a staging clone before production.\n",{"id":174,"difficulty":35,"q":175,"a":176},"ef-migration-columns-rename","How do you rename a column in an EF Core migration without losing data?","EF Core's `RenameColumn` migrates column names without dropping and recreating them,\npreserving existing data. Without it, EF would generate a `DropColumn` + `AddColumn`\npair, which deletes the data in that column.\n\n```csharp\n\u002F\u002F Step 1 — rename the property in the entity class:\npublic class Customer\n{\n    public int Id { get; set; }\n    \u002F\u002F Before: public string FullName { get; set; } = \"\";\n    public string DisplayName { get; set; } = \"\";  \u002F\u002F renamed property\n}\n\n\u002F\u002F Step 2 — generate the migration:\n\u002F\u002F dotnet ef migrations add RenameCustomerDisplayName\n\n\u002F\u002F The auto-generated migration MAY produce DropColumn + AddColumn (data loss!):\n\u002F\u002F Fix it manually to use RenameColumn instead:\npublic partial class RenameCustomerDisplayName : Migration\n{\n    protected override void Up(MigrationBuilder migrationBuilder)\n    {\n        \u002F\u002F Safe — preserves column data:\n        migrationBuilder.RenameColumn(\n            name: \"FullName\",\n            table: \"Customers\",\n            newName: \"DisplayName\");\n    }\n\n    protected override void Down(MigrationBuilder migrationBuilder)\n    {\n        migrationBuilder.RenameColumn(\n            name: \"DisplayName\",\n            table: \"Customers\",\n            newName: \"FullName\");\n    }\n}\n\n\u002F\u002F Step 3 — map the new column name to the property if needed:\nmodelBuilder.Entity\u003CCustomer>()\n    .Property(c => c.DisplayName)\n    .HasColumnName(\"DisplayName\"); \u002F\u002F explicit; EF derives it from property name by default\n```\n\n**Rule of thumb:** Always inspect auto-generated migrations before applying them.\nWhen renaming a column, replace any `DropColumn`\u002F`AddColumn` pair with a single\n`RenameColumn` call to avoid silent data loss.\n",{"id":178,"difficulty":96,"q":179,"a":180},"ef-migration-separate-assembly","How do you put EF Core migrations in a separate assembly from the DbContext?","Placing migrations in a dedicated assembly (e.g., `MyApp.Migrations`) keeps the\ndata layer clean and allows independent versioning. It requires configuring both\nthe `MigrationsAssembly` option and a design-time factory.\n\n```csharp\n\u002F\u002F Project layout:\n\u002F\u002F MyApp.Data        — contains AppDbContext, entity configs\n\u002F\u002F MyApp.Migrations  — contains only migration files\n\u002F\u002F MyApp.Api         — startup project\n\n\u002F\u002F In MyApp.Api Program.cs — tell EF where migrations live:\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options.UseSqlServer(\n        connectionString,\n        sql => sql.MigrationsAssembly(\"MyApp.Migrations\"))); \u002F\u002F assembly name\n\n\u002F\u002F In MyApp.Migrations — design-time factory so dotnet ef can build the context:\npublic class AppDbContextFactory : IDesignTimeDbContextFactory\u003CAppDbContext>\n{\n    public AppDbContext CreateDbContext(string[] args)\n    {\n        var config = new ConfigurationBuilder()\n            .SetBasePath(Directory.GetCurrentDirectory())\n            .AddJsonFile(\"appsettings.json\", optional: true)\n            .AddEnvironmentVariables()\n            .Build();\n\n        var opts = new DbContextOptionsBuilder\u003CAppDbContext>()\n            .UseSqlServer(\n                config.GetConnectionString(\"Default\"),\n                sql => sql.MigrationsAssembly(\"MyApp.Migrations\"))\n            .Options;\n\n        return new AppDbContext(opts);\n    }\n}\n```\n\n```bash\n# Generate a migration — target MyApp.Migrations, startup project MyApp.Api:\ndotnet ef migrations add InitialCreate \\\n    --project MyApp.Migrations \\\n    --startup-project MyApp.Api \\\n    --context AppDbContext\n\n# Apply:\ndotnet ef database update \\\n    --project MyApp.Migrations \\\n    --startup-project MyApp.Api\n```\n\n**Rule of thumb:** Move migrations to a separate assembly for large solutions where\nthe data layer is shared across multiple apps (e.g., web API + background worker).\nAlways keep `MigrationsAssembly` in sync between runtime registration and the\ndesign-time factory.\n",{"description":32},"EF Core migrations interview questions — Add-Migration, Up\u002FDown methods, MigrateAsync, migration bundles, seeding, and rollback strategies.","dotnet\u002Fentity-framework\u002Fmigrations","oMk5ZPvNRmGINCgzvsO_Xl5h7BqSVTuHIEWmeHTbRYg",{"id":186,"title":187,"body":188,"description":32,"difficulty":35,"extension":36,"framework":10,"frameworkSlug":8,"meta":192,"navigation":38,"order":193,"path":194,"questions":195,"questionsCount":103,"related":104,"seo":256,"seoDescription":257,"stem":258,"subtopic":187,"topic":19,"topicSlug":21,"updated":109,"__hash__":259},"qa\u002Fdotnet\u002Fentity-framework\u002Fquerying.md","Querying",{"type":29,"value":189,"toc":190},[],{"title":32,"searchDepth":33,"depth":33,"links":191},[],{},3,"\u002Fdotnet\u002Fentity-framework\u002Fquerying",[196,200,204,208,212,216,220,224,228,232,236,240,244,248,252],{"id":197,"difficulty":43,"q":198,"a":199},"ef-iqueryable-vs-ienumerable","What is the difference between IQueryable and IEnumerable in EF Core queries?","**`IQueryable\u003CT>`** builds an expression tree that EF Core translates to SQL —\nfiltering happens in the database. **`IEnumerable\u003CT>`** operates in memory —\nthe full result set is loaded first, then filtered in C#.\n\n```csharp\n\u002F\u002F IQueryable — WHERE clause runs on the DB:\nIQueryable\u003COrder> query = _db.Orders          \u002F\u002F still IQueryable — no SQL yet\n    .Where(o => o.CustomerId == customerId)    \u002F\u002F added to SQL: WHERE CustomerId = @p0\n    .Where(o => o.Total > 100);               \u002F\u002F added to SQL: AND Total > @p1\n\n\u002F\u002F Materialise — this is when SQL executes:\nvar orders = await query.ToListAsync();       \u002F\u002F SELECT ... WHERE CustomerId=? AND Total>?\n\n\u002F\u002F IEnumerable — loads ALL rows, then filters in memory:\nIEnumerable\u003COrder> allOrders = _db.Orders.AsEnumerable(); \u002F\u002F SELECT * FROM Orders (all rows!)\nvar expensive = allOrders.Where(o => o.Total > 100);      \u002F\u002F filtered in C# — too late\n\n\u002F\u002F Practical consequence:\npublic IQueryable\u003COrder> GetOrdersByCustomer(int id)\n    => _db.Orders.Where(o => o.CustomerId == id); \u002F\u002F callers can compose further SQL\n\npublic IEnumerable\u003COrder> GetOrdersByCustomerBad(int id)\n    => _db.Orders.Where(o => o.CustomerId == id).ToList(); \u002F\u002F materialised — composition lost\n```\n\n**Rule of thumb:** Keep queries as `IQueryable\u003CT>` until the last moment. Never call\n`.AsEnumerable()` or `.ToList()` mid-chain unless you intentionally want in-memory\nprocessing of a small set.\n",{"id":201,"difficulty":43,"q":202,"a":203},"ef-deferred-execution","What is deferred execution in EF Core and which operations trigger SQL?","EF Core queries are **deferred** — they build an expression tree but don't hit the\ndatabase until a **terminal operator** materialises the results.\n\n```csharp\n\u002F\u002F Building the query — NO SQL yet:\nvar query = _db.Orders\n    .Where(o => o.Status == \"Pending\")\n    .OrderBy(o => o.CreatedAt)\n    .Take(50);\n\n\u002F\u002F Terminal operators — each generates and executes SQL:\nvar list   = await query.ToListAsync();            \u002F\u002F SELECT ... (returns List\u003COrder>)\nvar first  = await query.FirstOrDefaultAsync();    \u002F\u002F SELECT TOP 1 ...\nvar count  = await query.CountAsync();             \u002F\u002F SELECT COUNT(*)\nvar any    = await query.AnyAsync();               \u002F\u002F SELECT CASE WHEN EXISTS(...)\nvar single = await query.SingleAsync();            \u002F\u002F SELECT ... (throws if 0 or 2+)\nvar array  = await query.ToArrayAsync();\nvar dict   = await query.ToDictionaryAsync(o => o.Id);\n\n\u002F\u002F foreach also triggers execution (but prefer ToListAsync for async):\nawait foreach (var order in query.AsAsyncEnumerable()) \u002F\u002F streaming — no full buffer\n    Process(order);\n\n\u002F\u002F Common mistake — calling the DB twice:\nvar q = _db.Products.Where(p => p.IsActive);\nvar count    = await q.CountAsync();  \u002F\u002F SELECT COUNT(*) — first trip\nvar products = await q.ToListAsync(); \u002F\u002F SELECT * — second trip\n\u002F\u002F Fix: do both in one query or materialise once.\n```\n\n**Rule of thumb:** A LINQ chain on `DbSet\u003CT>` is just a description. SQL executes\nonly at `ToListAsync`, `FirstOrDefaultAsync`, `CountAsync`, `AnyAsync`, etc.\nAvoid materialising the same query twice.\n",{"id":205,"difficulty":43,"q":206,"a":207},"ef-projection","How do you use projections (Select) to load only the columns you need?","**Projection** via `.Select()` instructs EF Core to generate a `SELECT` with only\nthe specified columns, reducing data transfer and avoiding unnecessary object overhead.\n\n```csharp\n\u002F\u002F Loads all columns including large blobs:\nvar orders = await _db.Orders\n    .Where(o => o.CustomerId == customerId)\n    .ToListAsync(); \u002F\u002F SELECT Id, CustomerId, Status, Total, Notes, Blob, ...\n\n\u002F\u002F Project to a DTO — only fetches needed columns:\nvar summaries = await _db.Orders\n    .Where(o => o.CustomerId == customerId)\n    .Select(o => new OrderSummaryDto\n    {\n        Id     = o.Id,\n        Status = o.Status,\n        Total  = o.Total\n    })\n    .ToListAsync(); \u002F\u002F SELECT Id, Status, Total FROM Orders WHERE CustomerId = @p0\n\n\u002F\u002F Anonymous type projection (quick\u002Flocal use):\nvar ids = await _db.Orders\n    .Where(o => o.Status == \"Pending\")\n    .Select(o => new { o.Id, o.CreatedAt })\n    .ToListAsync();\n\n\u002F\u002F Nested projection — joins happen in one query:\nvar result = await _db.Orders\n    .Select(o => new OrderDetailDto\n    {\n        Id           = o.Id,\n        CustomerName = o.Customer.Name,  \u002F\u002F JOIN generated automatically\n        Items        = o.Items.Select(i => new ItemDto\n        {\n            ProductName = i.Product.Name,\n            Quantity    = i.Quantity\n        }).ToList()\n    })\n    .ToListAsync();\n```\n\n**Rule of thumb:** Always project to a DTO or anonymous type when the query result\nis read-only. Loading full entities just to read two columns wastes bandwidth and\nmemory, especially for large tables.\n",{"id":209,"difficulty":35,"q":210,"a":211},"ef-eager-loading","What is eager loading and how do you use Include and ThenInclude?","**Eager loading** fetches related entities in the same query via SQL `JOIN` using\n`Include` and `ThenInclude`, avoiding separate round trips to the database.\n\n```csharp\n\u002F\u002F Without Include — navigation properties are null:\nvar order = await _db.Orders.FindAsync(42);\nConsole.WriteLine(order.Customer.Name); \u002F\u002F NullReferenceException — not loaded\n\n\u002F\u002F Include — adds a JOIN for the related table:\nvar order = await _db.Orders\n    .Include(o => o.Customer)                  \u002F\u002F JOIN Customers\n    .Include(o => o.Items)                     \u002F\u002F JOIN OrderItems\n    .FirstOrDefaultAsync(o => o.Id == 42);\n\n\u002F\u002F ThenInclude — navigate deeper into the graph:\nvar orders = await _db.Orders\n    .Include(o => o.Items)                     \u002F\u002F JOIN OrderItems\n        .ThenInclude(i => i.Product)           \u002F\u002F JOIN Products\n    .Include(o => o.Customer)\n        .ThenInclude(c => c.Address)           \u002F\u002F JOIN Addresses\n    .Where(o => o.Status == \"Pending\")\n    .ToListAsync();\n\n\u002F\u002F Filtered include (EF Core 5+) — only include a subset of related items:\nvar orders = await _db.Orders\n    .Include(o => o.Items.Where(i => !i.IsCancelled))\n    .ToListAsync();\n\n\u002F\u002F Include with AsNoTracking for read-only operations:\nvar orders = await _db.Orders\n    .AsNoTracking()\n    .Include(o => o.Items)\n    .ToListAsync();\n```\n\n**Rule of thumb:** Use `Include` for 1–2 levels of related data when you know you'll\nneed it. Deep or conditional includes can generate complex SQL — consider splitting\ninto multiple queries for very deep graphs.\n",{"id":213,"difficulty":35,"q":214,"a":215},"ef-n-plus-one","What is the N+1 query problem and how do you fix it in EF Core?","The **N+1 problem** occurs when code issues one query to load N parents, then N\nadditional queries — one per parent — to load a related collection. Total: N+1 queries.\n\n```csharp\n\u002F\u002F N+1 — lazy loading or iterating without Include:\nvar customers = await _db.Customers.ToListAsync(); \u002F\u002F Query 1: SELECT * FROM Customers\n\nforeach (var customer in customers)\n{\n    \u002F\u002F Query 2..N+1: SELECT * FROM Orders WHERE CustomerId = @id (once per customer!)\n    var count = customer.Orders.Count;\n    Console.WriteLine($\"{customer.Name}: {count} orders\");\n}\n\u002F\u002F 100 customers = 101 queries\n\n\u002F\u002F Fix 1 — eager load with Include:\nvar customers = await _db.Customers\n    .Include(c => c.Orders)\n    .ToListAsync(); \u002F\u002F 1 query with JOIN\n\n\u002F\u002F Fix 2 — project the count into the initial query:\nvar summary = await _db.Customers\n    .Select(c => new\n    {\n        c.Name,\n        OrderCount = c.Orders.Count  \u002F\u002F COUNT(*) in a subquery — 1 SQL statement\n    })\n    .ToListAsync();\n\n\u002F\u002F Fix 3 — split query (EF Core 5+) for very wide result sets:\nvar customers = await _db.Customers\n    .Include(c => c.Orders)\n    .AsSplitQuery()   \u002F\u002F 2 queries: one for Customers, one for Orders (no cartesian)\n    .ToListAsync();\n\n\u002F\u002F Detect N+1 in development with EF Core logging:\noptions.LogTo(Console.WriteLine, LogLevel.Information);\n\u002F\u002F or use MiniProfiler, EF Core interceptors, or Application Insights\n```\n\n**Rule of thumb:** Never loop over a collection and access a navigation property\ninside the loop without first loading it via `Include`. Enable query logging in\ndevelopment to catch N+1 patterns before they reach production.\n",{"id":217,"difficulty":35,"q":218,"a":219},"ef-lazy-loading","What is lazy loading in EF Core and why is it dangerous in web applications?","**Lazy loading** automatically loads navigation properties the first time they are\naccessed by issuing an additional query — convenient but dangerous in web APIs\nbecause it hides N+1 queries.\n\n```csharp\n\u002F\u002F Enable lazy loading via proxies:\n\u002F\u002F Install: dotnet add package Microsoft.EntityFrameworkCore.Proxies\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options\n        .UseSqlServer(connectionString)\n        .UseLazyLoadingProxies()); \u002F\u002F wraps entities in dynamic proxies\n\n\u002F\u002F Navigation properties must be virtual:\npublic class Order\n{\n    public int Id { get; set; }\n    public virtual Customer Customer { get; set; } \u002F\u002F loaded lazily on first access\n    public virtual ICollection\u003COrderItem> Items { get; set; } \u002F\u002F same\n}\n\n\u002F\u002F Lazy loading in a controller — silent N+1:\nvar orders = await _db.Orders.ToListAsync(); \u002F\u002F 1 query\nforeach (var o in orders)\n    Console.WriteLine(o.Customer.Name); \u002F\u002F +1 query PER ORDER — hidden!\n\n\u002F\u002F Lazy loading after DbContext is disposed:\nOrder GetOrder()\n{\n    using var db = new AppDbContext(opts);\n    return db.Orders.Find(1);\n} \u002F\u002F context disposed here\nvar order = GetOrder();\nConsole.WriteLine(order.Customer.Name); \u002F\u002F ObjectDisposedException\n\n\u002F\u002F Prefer explicit eager loading or projections:\nvar orders = await _db.Orders.Include(o => o.Customer).ToListAsync();\n```\n\n**Rule of thumb:** Disable lazy loading in web APIs. Use explicit `Include` or\nprojections so every query is visible and intentional. Lazy loading belongs only in\ndesktop or interactive applications where the context lives long enough.\n",{"id":221,"difficulty":35,"q":222,"a":223},"ef-raw-sql","When and how do you execute raw SQL in EF Core?","EF Core provides raw SQL APIs for queries that LINQ can't express — full-text search,\nstored procedures, database-specific functions, and bulk operations.\n\n```csharp\n\u002F\u002F FromSqlRaw — raw SQL that returns entity rows (can compose LINQ on top):\nvar orders = await _db.Orders\n    .FromSqlRaw(\"SELECT * FROM Orders WHERE Status = {0}\", \"Pending\")\n    .Where(o => o.Total > 100)    \u002F\u002F LINQ composed on top of the raw SQL\n    .OrderBy(o => o.CreatedAt)\n    .ToListAsync();\n\n\u002F\u002F FromSqlInterpolated — safer, uses parameterized queries automatically:\nstring status = \"Pending\";\nvar orders = await _db.Orders\n    .FromSqlInterpolated($\"SELECT * FROM Orders WHERE Status = {status}\")\n    .ToListAsync();\n\n\u002F\u002F ExecuteSqlRawAsync — non-query statements (no entity return):\nint rows = await _db.Database.ExecuteSqlRawAsync(\n    \"DELETE FROM Orders WHERE CreatedAt \u003C {0} AND Status = {1}\",\n    cutoff, \"Cancelled\");\n\n\u002F\u002F ExecuteSqlInterpolatedAsync — same but parameterized via interpolation:\nawait _db.Database.ExecuteSqlInterpolatedAsync(\n    $\"UPDATE Products SET Stock = Stock - {quantity} WHERE Id = {productId}\");\n\n\u002F\u002F Calling a stored procedure that returns entities:\nvar results = await _db.Orders\n    .FromSqlRaw(\"EXEC sp_GetPendingOrders @CustomerId = {0}\", customerId)\n    .ToListAsync();\n\n\u002F\u002F SQL injection risk — NEVER string-concatenate user input:\nstring unsafe = $\"SELECT * FROM Orders WHERE Status = '{userInput}'\"; \u002F\u002F vulnerable!\n\u002F\u002F Always use parameterized overloads.\n```\n\n**Rule of thumb:** Use parameterized `FromSqlInterpolated` and\n`ExecuteSqlInterpolatedAsync` — not `Raw` variants — whenever the SQL includes any\nuser-provided values. EF Core's interpolation converts `{variable}` to DB parameters\nautomatically.\n",{"id":225,"difficulty":43,"q":226,"a":227},"ef-async-queries","Why should EF Core queries always use async methods like ToListAsync?","**Async EF Core queries** (`ToListAsync`, `FirstOrDefaultAsync`, etc.) release the\nthread to the thread pool while waiting for the database, improving throughput under\nconcurrent load.\n\n```csharp\n\u002F\u002F Async — thread released to pool while DB executes:\nvar orders = await _db.Orders\n    .Where(o => o.Status == \"Pending\")\n    .ToListAsync(cancellationToken); \u002F\u002F thread free during DB wait\n\n\u002F\u002F Sync — thread blocks for the entire DB round trip:\nvar orders = _db.Orders\n    .Where(o => o.Status == \"Pending\")\n    .ToList(); \u002F\u002F thread occupied — in ASP.NET Core this wastes a thread pool slot\n\n\u002F\u002F .Result \u002F .Wait() — causes deadlocks in ASP.NET Core:\nvar orders = _db.Orders.ToListAsync().Result; \u002F\u002F potential deadlock\n\n\u002F\u002F Use CancellationToken throughout:\npublic async Task\u003CList\u003COrder>> GetPendingAsync(CancellationToken ct)\n    => await _db.Orders\n        .Where(o => o.Status == \"Pending\")\n        .AsNoTracking()\n        .ToListAsync(ct); \u002F\u002F honours request cancellation (client disconnect)\n\n\u002F\u002F Stream large result sets with AsAsyncEnumerable:\nawait foreach (var order in _db.Orders.AsAsyncEnumerable())\n{\n    await ProcessAsync(order); \u002F\u002F process one at a time — no full buffer in memory\n}\n```\n\n**Rule of thumb:** Always use `*Async` EF Core methods in ASP.NET Core and pass the\n`CancellationToken` from the action or endpoint. Sync calls waste thread pool threads\nand block under load.\n",{"id":229,"difficulty":96,"q":230,"a":231},"ef-compiled-queries","What are compiled queries in EF Core and when do they give a measurable speedup?","**Compiled queries** (`EF.CompileAsyncQuery`) pre-compile the LINQ expression to SQL\nonce at startup and cache the result, skipping query translation on every call.\nUseful for hot paths called thousands of times per second.\n\n```csharp\n\u002F\u002F Standard query — translates LINQ to SQL on every call:\npublic async Task\u003COrder?> GetOrderAsync(int id)\n    => await _db.Orders.FirstOrDefaultAsync(o => o.Id == id);\n\u002F\u002F EF Core caches most queries internally, but compilation still has overhead.\n\n\u002F\u002F Compiled query — translation happens once at class initialisation:\nprivate static readonly Func\u003CAppDbContext, int, Task\u003COrder?>> GetOrderById =\n    EF.CompileAsyncQuery(\n        (AppDbContext db, int id) =>\n            db.Orders.FirstOrDefault(o => o.Id == id));\n\n\u002F\u002F Usage — no translation overhead:\nvar order = await GetOrderById(_db, id);\n\n\u002F\u002F With a collection parameter:\nprivate static readonly Func\u003CAppDbContext, IEnumerable\u003Cint>, IAsyncEnumerable\u003COrder>> GetOrdersByIds =\n    EF.CompileAsyncQuery(\n        (AppDbContext db, IEnumerable\u003Cint> ids) =>\n            db.Orders.Where(o => ids.Contains(o.Id)));\n\nawait foreach (var order in GetOrdersByIds(_db, new[] { 1, 2, 3 }))\n    Process(order);\n```\n\nWhen to use compiled queries:\n- Hot paths: endpoint called 1,000+ times\u002Fsecond where query planning overhead is measurable.\n- The query shape is fixed — no dynamic `Where` conditions or `Include` changes.\n- Profiling confirms EF's internal cache isn't enough.\n\n**Rule of thumb:** Don't reach for compiled queries prematurely. EF Core caches most\nqueries internally. Compiled queries pay off only on very hot, fixed-shape paths;\nmeasure first.\n",{"id":233,"difficulty":35,"q":234,"a":235},"ef-split-queries","What are split queries in EF Core and when should you use them?","**Split queries** (`AsSplitQuery`) execute a single LINQ query as multiple SQL queries\nrather than one query with multiple JOINs, avoiding the **Cartesian explosion** that\noccurs when including multiple collections.\n\n```csharp\n\u002F\u002F Single query with multiple collection includes — Cartesian explosion:\n\u002F\u002F Orders × Items × Tags → each combination is a row; rows multiply rapidly\nvar orders = await _db.Orders\n    .Include(o => o.Items)   \u002F\u002F 10 items each\n    .Include(o => o.Tags)    \u002F\u002F 5 tags each\n    .ToListAsync();\n\u002F\u002F Generates: SELECT ... FROM Orders JOIN OrderItems JOIN Tags\n\u002F\u002F 100 orders × 10 items × 5 tags = 5,000 rows transferred\n\n\u002F\u002F Split query — 3 separate SQL statements:\nvar orders = await _db.Orders\n    .Include(o => o.Items)\n    .Include(o => o.Tags)\n    .AsSplitQuery()          \u002F\u002F 3 SQL queries: Orders, Items, Tags\n    .ToListAsync();\n\u002F\u002F Each table queried once; no Cartesian product\n\n\u002F\u002F Set split query as the global default:\nbuilder.Services.AddDbContext\u003CAppDbContext>(options =>\n    options.UseSqlServer(connectionString,\n        sql => sql.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)));\n\n\u002F\u002F Override back to single query when needed:\nvar orders = await _db.Orders\n    .Include(o => o.Customer)    \u002F\u002F just one navigation — no explosion\n    .AsSingleQuery()\n    .ToListAsync();\n```\n\nTrade-offs of split queries:\n- **Pro:** avoids Cartesian explosion for multiple collection includes.\n- **Con:** multiple round trips — inconsistent if data changes between them.\n- **Con:** no transaction by default — wrap in one if consistency matters.\n\n**Rule of thumb:** Use `AsSplitQuery` when including two or more collections on the\nsame entity. Use single query when including only reference navigations or one collection.\n",{"id":237,"difficulty":35,"q":238,"a":239},"ef-groupby-aggregations","How does EF Core translate GroupBy and aggregate functions to SQL?","EF Core translates `GroupBy` with aggregate functions (`Count`, `Sum`, `Average`,\n`Min`, `Max`) directly to `GROUP BY` SQL. Without aggregation, it falls back to\nclient-side grouping after loading all rows — a common performance trap.\n\n```csharp\n\u002F\u002F GroupBy + aggregate — translated to SQL GROUP BY:\nvar ordersByStatus = await _db.Orders\n    .GroupBy(o => o.Status)\n    .Select(g => new\n    {\n        Status = g.Key,\n        Count  = g.Count(),\n        Total  = g.Sum(o => o.Total)\n    })\n    .ToListAsync();\n\u002F\u002F SQL: SELECT Status, COUNT(*), SUM(Total) FROM Orders GROUP BY Status\n\n\u002F\u002F Multiple keys:\nvar byCustomerAndMonth = await _db.Orders\n    .GroupBy(o => new { o.CustomerId, Month = o.CreatedAt.Month })\n    .Select(g => new\n    {\n        g.Key.CustomerId,\n        g.Key.Month,\n        Count = g.Count(),\n        Revenue = g.Sum(o => o.Total)\n    })\n    .ToListAsync();\n\u002F\u002F SQL: GROUP BY CustomerId, MONTH(CreatedAt)\n\n\u002F\u002F GroupBy without aggregate — EF falls back to client evaluation:\nvar groups = await _db.Orders\n    .GroupBy(o => o.Status)\n    .ToListAsync(); \u002F\u002F SELECT * FROM Orders — loads ALL rows, groups in memory\n\u002F\u002F In EF Core 3+, this throws or warns. Always project to aggregates.\n\n\u002F\u002F HAVING clause — filter groups by aggregate:\nvar activeCustomers = await _db.Orders\n    .GroupBy(o => o.CustomerId)\n    .Where(g => g.Count() >= 5)     \u002F\u002F translated to HAVING COUNT(*) >= 5\n    .Select(g => new { CustomerId = g.Key, OrderCount = g.Count() })\n    .ToListAsync();\n```\n\n**Rule of thumb:** Always combine `GroupBy` with at least one aggregate function\n(`Count`, `Sum`, etc.) in the `Select`. Without it, EF Core 3+ either throws or\nloads the entire table into memory.\n",{"id":241,"difficulty":43,"q":242,"a":243},"ef-no-tracking","What is AsNoTracking and when should you use it?","**`AsNoTracking()`** instructs EF Core to skip change tracking for a query's results.\nThe returned entities are disconnected from the context — changes to them are not\ndetected by `SaveChanges`.\n\n```csharp\n\u002F\u002F Default (tracked) — entities registered with the change tracker:\nvar order = await _db.Orders.FindAsync(42);\norder.Status = \"Shipped\";\nawait _db.SaveChangesAsync(); \u002F\u002F detects change, generates UPDATE\n\n\u002F\u002F AsNoTracking — entities are plain C# objects, no change tracker registration:\nvar orders = await _db.Orders\n    .AsNoTracking()\n    .Where(o => o.Status == \"Pending\")\n    .ToListAsync();\n\u002F\u002F Faster: no identity map lookup, no snapshot copy, lower memory\n\n\u002F\u002F AsNoTrackingWithIdentityResolution (EF Core 5+) — no tracking BUT\n\u002F\u002F returns the same object instance for the same PK within the query:\nvar orders = await _db.Orders\n    .AsNoTrackingWithIdentityResolution()\n    .Include(o => o.Customer)\n    .ToListAsync();\n\u002F\u002F Multiple orders sharing the same customer → same Customer object in memory\n\n\u002F\u002F Global default for a context (read-heavy reporting context):\npublic class ReportDbContext : DbContext\n{\n    protected override void OnConfiguring(DbContextOptionsBuilder b)\n        => b.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);\n}\n```\n\nBenchmarks typically show **10–20% faster query materialisation** and **lower GC\npressure** with `AsNoTracking` on large result sets.\n\n**Rule of thumb:** Add `AsNoTracking()` to every query in a read-only path (API\nGET endpoints, reports, search). Only track entities you plan to modify and save.\n",{"id":245,"difficulty":43,"q":246,"a":247},"ef-pagination","How do you implement pagination with EF Core?","**Pagination** in EF Core is achieved with `.Skip()` and `.Take()` which translate\nto `OFFSET` \u002F `FETCH NEXT` (or equivalent) in SQL. Always combine with `OrderBy`\nso results are deterministic.\n\n```csharp\n\u002F\u002F Offset-based pagination — page 1 = skip 0, page 2 = skip pageSize, etc.:\npublic async Task\u003CPagedResult\u003COrderSummaryDto>> GetOrdersAsync(int page, int pageSize)\n{\n    var query = _db.Orders\n        .AsNoTracking()\n        .Where(o => o.Status == \"Pending\")\n        .OrderByDescending(o => o.CreatedAt); \u002F\u002F required — results are non-deterministic without it\n\n    var total = await query.CountAsync(); \u002F\u002F SELECT COUNT(*) — same filter\n\n    var items = await query\n        .Skip((page - 1) * pageSize) \u002F\u002F OFFSET\n        .Take(pageSize)              \u002F\u002F FETCH NEXT\n        .Select(o => new OrderSummaryDto\n        {\n            Id     = o.Id,\n            Status = o.Status,\n            Total  = o.Total\n        })\n        .ToListAsync();\n\n    return new PagedResult\u003COrderSummaryDto>(items, total, page, pageSize);\n}\n\u002F\u002F SQL: SELECT Id, Status, Total FROM Orders WHERE Status='Pending'\n\u002F\u002F      ORDER BY CreatedAt DESC OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY\n\n\u002F\u002F Keyset (cursor) pagination — faster for large offsets:\n\u002F\u002F Instead of SKIP, filter by the last seen value:\nvar items = await _db.Orders\n    .AsNoTracking()\n    .Where(o => o.CreatedAt \u003C lastSeenCreatedAt) \u002F\u002F cursor\n    .OrderByDescending(o => o.CreatedAt)\n    .Take(pageSize)\n    .ToListAsync();\n\u002F\u002F No OFFSET scan — index seek directly to the cursor position\n```\n\n**Rule of thumb:** Use offset pagination for small datasets where any page can be\njumped to. Use keyset (cursor) pagination for large tables or infinite scroll — it\nscales to millions of rows without degrading as the page number grows.\n",{"id":249,"difficulty":43,"q":250,"a":251},"ef-like-contains-search","How do you perform text search (LIKE, full-text) with EF Core?","EF Core translates `.Contains()`, `.StartsWith()`, and `.EndsWith()` to SQL `LIKE`\npatterns. For full-text search, use `EF.Functions.Like` or database-specific functions.\n\n```csharp\n\u002F\u002F Contains → LIKE '%value%' (substring search — can't use an index efficiently):\nvar results = await _db.Products\n    .AsNoTracking()\n    .Where(p => p.Name.Contains(\"widget\"))\n    .ToListAsync();\n\u002F\u002F SQL: WHERE Name LIKE '%widget%'\n\n\u002F\u002F StartsWith → LIKE 'value%' (prefix — can use a B-tree index):\nvar results = await _db.Products\n    .Where(p => p.Sku.StartsWith(\"WGT-\"))\n    .ToListAsync();\n\u002F\u002F SQL: WHERE Sku LIKE 'WGT-%'\n\n\u002F\u002F EF.Functions.Like — more control over the pattern:\nvar results = await _db.Products\n    .Where(p => EF.Functions.Like(p.Name, \"%wid_et%\")) \u002F\u002F _ matches one character\n    .ToListAsync();\n\n\u002F\u002F Case-insensitive comparison (depends on DB collation; explicit on SQLite):\nvar results = await _db.Products\n    .Where(p => EF.Functions.Like(p.Name, \"%widget%\")) \u002F\u002F case-insensitive on SQL Server default collation\n\n\u002F\u002F SQL Server full-text search (requires FTS index on the column):\nvar results = await _db.Products\n    .Where(p => EF.Functions.Contains(p.Description, \"widget OR gadget\"))\n    .ToListAsync();\n\u002F\u002F SQL: WHERE CONTAINS(Description, 'widget OR gadget')\n\n\u002F\u002F Warning: never pass unvalidated user input directly into EF.Functions.Like —\n\u002F\u002F the pattern itself is parameterized, but wildcard injection is still possible:\nstring safe = $\"%{userInput.Replace(\"%\", \"[%]\").Replace(\"_\", \"[_]\")}%\";\n```\n\n**Rule of thumb:** Use `StartsWith` for prefix search on indexed columns. Use\n`Contains` sparingly — `LIKE '%value%'` causes full table scans. Use database\nfull-text search (`EF.Functions.Contains`) for production text search requirements.\n",{"id":253,"difficulty":35,"q":254,"a":255},"ef-explicit-loading","What is explicit loading in EF Core and how does it differ from eager and lazy loading?","**Explicit loading** loads a navigation property on demand after the entity is already\nin memory — using `LoadAsync` on the entry's reference or collection. Unlike lazy loading\nit is intentional and visible in code; unlike eager loading it's a separate SQL round trip.\n\n```csharp\n\u002F\u002F Load the entity first (navigation not included):\nvar order = await _db.Orders.FindAsync(42); \u002F\u002F SELECT * FROM Orders WHERE Id=42\n\n\u002F\u002F Explicit load — second query, triggered intentionally:\nawait _db.Entry(order)\n         .Reference(o => o.Customer)  \u002F\u002F reference navigation (single entity)\n         .LoadAsync();\n\u002F\u002F SQL: SELECT * FROM Customers WHERE Id = @customerId\n\nawait _db.Entry(order)\n         .Collection(o => o.Items)    \u002F\u002F collection navigation\n         .LoadAsync();\n\u002F\u002F SQL: SELECT * FROM OrderItems WHERE OrderId = 42\n\n\u002F\u002F Filter the collection while loading (EF Core 5+):\nawait _db.Entry(order)\n         .Collection(o => o.Items)\n         .Query()                                  \u002F\u002F IQueryable on the collection\n         .Where(i => !i.IsCancelled)\n         .LoadAsync();\n\u002F\u002F SQL: SELECT * FROM OrderItems WHERE OrderId=42 AND IsCancelled=0\n\n\u002F\u002F Comparison:\n\u002F\u002F Eager  (Include)   — one query with JOIN, loaded before you need it\n\u002F\u002F Lazy               — automatic, invisible, N+1 risk\n\u002F\u002F Explicit (LoadAsync) — extra query, but intentional and filterable\n\n\u002F\u002F Check before loading to avoid a redundant query:\nvar entry = _db.Entry(order);\nif (!entry.Collection(o => o.Items).IsLoaded)\n    await entry.Collection(o => o.Items).LoadAsync();\n```\n\n**Rule of thumb:** Use explicit loading when you don't know at query time whether\nyou'll need the related data — for example, conditional logic that only sometimes\nneeds the collection. For always-needed data, prefer `Include` to load everything\nin one round trip.\n",{"description":32},"EF Core querying interview questions — IQueryable vs IEnumerable, eager loading, the N+1 problem, projections, raw SQL, and compiled queries.","dotnet\u002Fentity-framework\u002Fquerying","Tvzik-2CyfM3KJu1hNE7UOaK6Lki1wBDLbXGqCzNxvc",{"id":261,"title":262,"body":263,"description":32,"difficulty":35,"extension":36,"framework":10,"frameworkSlug":8,"meta":267,"navigation":38,"order":268,"path":269,"questions":270,"questionsCount":103,"related":104,"seo":331,"seoDescription":332,"stem":333,"subtopic":262,"topic":19,"topicSlug":21,"updated":109,"__hash__":334},"qa\u002Fdotnet\u002Fentity-framework\u002Frelationships.md","Relationships",{"type":29,"value":264,"toc":265},[],{"title":32,"searchDepth":33,"depth":33,"links":266},[],{},4,"\u002Fdotnet\u002Fentity-framework\u002Frelationships",[271,275,279,283,287,291,295,299,303,307,311,315,319,323,327],{"id":272,"difficulty":43,"q":273,"a":274},"ef-one-to-many","How do you configure a one-to-many relationship in EF Core?","A **one-to-many** relationship has one principal entity linked to many dependent\nentities. EF Core can infer it from navigation properties and FK naming conventions,\nor you can configure it explicitly with Fluent API.\n\n```csharp\n\u002F\u002F Domain model:\npublic class Customer\n{\n    public int Id { get; set; }\n    public string Name { get; set; } = \"\";\n    public ICollection\u003COrder> Orders { get; set; } = new List\u003COrder>(); \u002F\u002F navigation\n}\n\npublic class Order\n{\n    public int Id { get; set; }\n    public int CustomerId { get; set; }     \u002F\u002F FK property (conventional name → inferred)\n    public Customer Customer { get; set; } = null!; \u002F\u002F reference navigation\n    public decimal Total { get; set; }\n}\n\n\u002F\u002F EF Core convention: Finds CustomerId FK automatically — no Fluent API needed.\n\n\u002F\u002F Explicit Fluent API (preferred for clarity and complex cases):\npublic class OrderConfiguration : IEntityTypeConfiguration\u003COrder>\n{\n    public void Configure(EntityTypeBuilder\u003COrder> b)\n    {\n        b.HasOne(o => o.Customer)           \u002F\u002F Order has one Customer\n         .WithMany(c => c.Orders)           \u002F\u002F Customer has many Orders\n         .HasForeignKey(o => o.CustomerId)  \u002F\u002F FK column\n         .IsRequired()                      \u002F\u002F NOT NULL in DB\n         .OnDelete(DeleteBehavior.Restrict); \u002F\u002F don't cascade\n    }\n}\n\n\u002F\u002F Querying:\nvar customerWithOrders = await _db.Customers\n    .Include(c => c.Orders)\n    .FirstOrDefaultAsync(c => c.Id == 1);\n```\n\n**Rule of thumb:** Declare both the FK property (`CustomerId`) and the navigation\n(`Customer`) on the dependent. Explicit Fluent API beats convention for any non-trivial\nrelationship — clarity is worth the extra lines.\n",{"id":276,"difficulty":35,"q":277,"a":278},"ef-many-to-many","How has many-to-many relationship configuration changed between EF Core 3 and EF Core 5+?","EF Core 5+ supports **implicit many-to-many** — no join entity class required.\nEF Core 3 required an explicit join table entity with two one-to-many relationships.\n\n```csharp\n\u002F\u002F EF Core 5+ — implicit many-to-many (no join entity):\npublic class Post\n{\n    public int Id { get; set; }\n    public ICollection\u003CTag> Tags { get; set; } = new List\u003CTag>(); \u002F\u002F navigation\n}\n\npublic class Tag\n{\n    public int Id { get; set; }\n    public string Name { get; set; } = \"\";\n    public ICollection\u003CPost> Posts { get; set; } = new List\u003CPost>(); \u002F\u002F navigation\n}\n\n\u002F\u002F EF Core infers a join table \"PostTag\" (PostsId, TagsId) automatically.\n\u002F\u002F Fluent API to customise the join table name and columns:\nmodelBuilder.Entity\u003CPost>()\n    .HasMany(p => p.Tags)\n    .WithMany(t => t.Posts)\n    .UsingEntity(j => j.ToTable(\"PostTags\")); \u002F\u002F rename join table\n\n\u002F\u002F Explicit join entity (required when join has extra payload columns):\npublic class PostTag\n{\n    public int PostId { get; set; }\n    public int TagId  { get; set; }\n    public DateTime TaggedAt { get; set; } \u002F\u002F extra column on the join\n    public Post Post { get; set; } = null!;\n    public Tag  Tag  { get; set; } = null!;\n}\n\nmodelBuilder.Entity\u003CPostTag>()\n    .HasKey(pt => new { pt.PostId, pt.TagId }); \u002F\u002F composite PK\n\nmodelBuilder.Entity\u003CPostTag>()\n    .HasOne(pt => pt.Post).WithMany(p => p.PostTags).HasForeignKey(pt => pt.PostId);\n\nmodelBuilder.Entity\u003CPostTag>()\n    .HasOne(pt => pt.Tag).WithMany(t => t.PostTags).HasForeignKey(pt => pt.TagId);\n```\n\n**Rule of thumb:** Use implicit many-to-many (EF Core 5+) when the join has no extra\ncolumns. Use an explicit join entity as soon as you need additional payload on the join\n(timestamps, flags, ordering).\n",{"id":280,"difficulty":35,"q":281,"a":282},"ef-one-to-one","How do you configure a one-to-one relationship in EF Core?","A **one-to-one** relationship links exactly one principal to at most one dependent.\nEF Core requires you to specify which end holds the FK because it can't infer it\nwhen both navigations are present.\n\n```csharp\n\u002F\u002F Domain model:\npublic class User\n{\n    public int Id { get; set; }\n    public string Email { get; set; } = \"\";\n    public UserProfile? Profile { get; set; } \u002F\u002F optional navigation to dependent\n}\n\npublic class UserProfile\n{\n    public int Id { get; set; }\n    public int UserId { get; set; }              \u002F\u002F FK lives on the dependent\n    public User User { get; set; } = null!;\n    public string Bio { get; set; } = \"\";\n}\n\n\u002F\u002F Fluent API — must declare which side has the FK:\npublic class UserProfileConfiguration : IEntityTypeConfiguration\u003CUserProfile>\n{\n    public void Configure(EntityTypeBuilder\u003CUserProfile> b)\n    {\n        b.HasOne(p => p.User)           \u002F\u002F UserProfile has one User\n         .WithOne(u => u.Profile)       \u002F\u002F User has one Profile\n         .HasForeignKey\u003CUserProfile>(p => p.UserId) \u002F\u002F FK on dependent side\n         .IsRequired()\n         .OnDelete(DeleteBehavior.Cascade); \u002F\u002F delete profile when user deleted\n\n        b.HasIndex(p => p.UserId).IsUnique(); \u002F\u002F enforce one-to-one at DB level\n    }\n}\n\n\u002F\u002F Querying:\nvar user = await _db.Users\n    .Include(u => u.Profile)\n    .FirstOrDefaultAsync(u => u.Id == userId);\n```\n\n**Rule of thumb:** Always place the FK on the dependent (the entity that can't exist\nwithout the other). Add a unique index on the FK column in the database — EF doesn't\nadd it automatically for one-to-one.\n",{"id":284,"difficulty":43,"q":285,"a":286},"ef-navigation-properties","What are navigation properties in EF Core and what are the different types?","**Navigation properties** are class members that reference related entity objects.\nEF Core uses them to build SQL JOINs and maintain the object graph.\n\n```csharp\npublic class Order\n{\n    public int Id { get; set; }\n    public int CustomerId { get; set; }\n\n    \u002F\u002F Reference navigation — points to a single related entity:\n    public Customer Customer { get; set; } = null!;\n\n    \u002F\u002F Collection navigation — points to multiple related entities:\n    public ICollection\u003COrderItem> Items { get; set; } = new List\u003COrderItem>();\n}\n\npublic class OrderItem\n{\n    public int Id { get; set; }\n    public int OrderId { get; set; }\n    public int ProductId { get; set; }\n\n    \u002F\u002F Inverse reference navigation (back to the principal):\n    public Order Order { get; set; } = null!;\n\n    \u002F\u002F Second reference navigation:\n    public Product Product { get; set; } = null!;\n    public int Quantity { get; set; }\n}\n\n\u002F\u002F Always initialise collection navigations to avoid null checks:\npublic ICollection\u003COrderItem> Items { get; set; } = new List\u003COrderItem>();\n\u002F\u002F Or in constructor: Items = new HashSet\u003COrderItem>();\n\n\u002F\u002F Reference navigations should be nullable (not always loaded):\npublic Customer? Customer { get; set; }\n\n\u002F\u002F Check if a navigation is loaded:\nbool isLoaded = _db.Entry(order).Reference(o => o.Customer).IsLoaded;\nbool collLoaded = _db.Entry(order).Collection(o => o.Items).IsLoaded;\n\n\u002F\u002F Explicitly load a navigation on demand:\nawait _db.Entry(order).Reference(o => o.Customer).LoadAsync();\nawait _db.Entry(order).Collection(o => o.Items).LoadAsync();\n```\n\n**Rule of thumb:** Initialise collection navigations to empty collections\n(`new List\u003CT>()`) to prevent `NullReferenceException`. Make reference navigations\nnullable to signal they might not be loaded.\n",{"id":288,"difficulty":35,"q":289,"a":290},"ef-cascade-delete","What is cascade delete in EF Core and what are the DeleteBehavior options?","**Cascade delete** automatically deletes dependent rows when the principal is deleted.\nEF Core exposes four `DeleteBehavior` options with different safety profiles.\n\n```csharp\n\u002F\u002F DeleteBehavior options:\n\u002F\u002F Cascade    — DB deletes dependents automatically (or EF tracks and deletes them)\n\u002F\u002F Restrict   — throws if dependents exist — safest for accidental deletes\n\u002F\u002F SetNull    — sets the FK to NULL on dependents (FK must be nullable)\n\u002F\u002F NoAction   — no action on DB delete; the application must manage orphans\n\npublic class OrderConfiguration : IEntityTypeConfiguration\u003COrder>\n{\n    public void Configure(EntityTypeBuilder\u003COrder> b)\n    {\n        \u002F\u002F Cascade — deleting Customer deletes all their Orders:\n        b.HasOne(o => o.Customer)\n         .WithMany(c => c.Orders)\n         .HasForeignKey(o => o.CustomerId)\n         .OnDelete(DeleteBehavior.Cascade);\n\n        \u002F\u002F Restrict — can't delete a Customer with existing Orders:\n        b.HasOne(o => o.Customer)\n         .WithMany(c => c.Orders)\n         .HasForeignKey(o => o.CustomerId)\n         .OnDelete(DeleteBehavior.Restrict);\n\n        \u002F\u002F SetNull — deleting Supplier sets Order.SupplierId to NULL:\n        b.HasOne(o => o.Supplier)\n         .WithMany(s => s.Orders)\n         .HasForeignKey(o => o.SupplierId)   \u002F\u002F SupplierId is int? (nullable)\n         .OnDelete(DeleteBehavior.SetNull);\n    }\n}\n\n\u002F\u002F EF Core's default: Cascade for required relationships, SetNull for optional.\n\u002F\u002F SQL Server default: NO ACTION (needs EF to cascade explicitly).\n\n\u002F\u002F Soft delete avoids all cascade concerns:\norder.IsDeleted = true;\nawait _db.SaveChangesAsync(); \u002F\u002F no FK violations\n```\n\n**Rule of thumb:** Prefer `Restrict` for business-critical data (orders, invoices)\nto prevent accidental mass deletes. Use `Cascade` only for true parent-child where\nthe child has no meaning without the parent (e.g., order → order items).\n",{"id":292,"difficulty":35,"q":293,"a":294},"ef-owned-entities","What are owned entity types in EF Core and when should you use them?","**Owned entities** are value-object-like types that belong exclusively to one owner\nentity. They share the owner's table by default (no separate `Id` column) and have\nno independent lifecycle.\n\n```csharp\n\u002F\u002F Domain model — Address is a value object:\npublic class Address\n{\n    public string Street { get; set; } = \"\";\n    public string City   { get; set; } = \"\";\n    public string Zip    { get; set; } = \"\";\n    \u002F\u002F No Id — Address is owned by Customer\n}\n\npublic class Customer\n{\n    public int Id { get; set; }\n    public string Name { get; set; } = \"\";\n    public Address ShippingAddress { get; set; } = new();\n    public Address BillingAddress  { get; set; } = new();\n}\n\n\u002F\u002F Configuration:\nmodelBuilder.Entity\u003CCustomer>()\n    .OwnsOne(c => c.ShippingAddress, addr =>\n    {\n        addr.Property(a => a.Street).HasColumnName(\"Ship_Street\").HasMaxLength(100);\n        addr.Property(a => a.City).HasColumnName(\"Ship_City\");\n        addr.Property(a => a.Zip).HasColumnName(\"Ship_Zip\");\n    });\n\nmodelBuilder.Entity\u003CCustomer>()\n    .OwnsOne(c => c.BillingAddress, addr =>\n    {\n        addr.Property(a => a.Street).HasColumnName(\"Bill_Street\");\n        \u002F\u002F ...\n    });\n\u002F\u002F Schema: Customers table contains Ship_Street, Ship_City, ... Bill_Street, etc.\n\n\u002F\u002F Store as JSON column (EF Core 7+):\nmodelBuilder.Entity\u003CCustomer>()\n    .OwnsOne(c => c.ShippingAddress, addr => addr.ToJson());\n\u002F\u002F Customers.ShippingAddress JSON column: {\"Street\":\"...\",\"City\":\"...\",\"Zip\":\"...\"}\n```\n\n**Rule of thumb:** Use `OwnsOne` \u002F `OwnsMany` for value objects that belong to one\nentity and have no independent identity. This maps cleanly to DDD value objects and\nkeeps the schema tidy.\n",{"id":296,"difficulty":35,"q":297,"a":298},"ef-self-referencing","How do you configure a self-referencing (hierarchical) relationship in EF Core?","A **self-referencing relationship** points from an entity back to itself — used for\ntrees and hierarchies (categories, organisational charts, comments with replies).\n\n```csharp\n\u002F\u002F Category tree — each category optionally has a parent:\npublic class Category\n{\n    public int Id { get; set; }\n    public string Name { get; set; } = \"\";\n    public int? ParentId { get; set; }                \u002F\u002F nullable FK — root has no parent\n    public Category? Parent { get; set; }             \u002F\u002F reference navigation (up)\n    public ICollection\u003CCategory> Children { get; set; } = new List\u003CCategory>(); \u002F\u002F down\n}\n\n\u002F\u002F Configuration — works by convention, but explicit is clearer:\nmodelBuilder.Entity\u003CCategory>()\n    .HasOne(c => c.Parent)\n    .WithMany(c => c.Children)\n    .HasForeignKey(c => c.ParentId)\n    .IsRequired(false)              \u002F\u002F nullable FK — root nodes have null ParentId\n    .OnDelete(DeleteBehavior.Restrict); \u002F\u002F prevent accidental tree deletion\n\n\u002F\u002F Load the full tree with recursive includes (small trees only):\nvar root = await _db.Categories\n    .Include(c => c.Children)\n        .ThenInclude(c => c.Children)    \u002F\u002F 3 levels deep\n    .Where(c => c.ParentId == null)      \u002F\u002F root nodes\n    .ToListAsync();\n\n\u002F\u002F For deep trees, load all and build the hierarchy in memory:\nvar all = await _db.Categories.AsNoTracking().ToListAsync();\nvar roots = all.Where(c => c.ParentId == null).ToList();\nvar byParent = all.Where(c => c.ParentId != null)\n                  .GroupBy(c => c.ParentId!.Value)\n                  .ToDictionary(g => g.Key, g => g.ToList());\n```\n\n**Rule of thumb:** Keep self-referencing relationships in relational databases for\nshallow trees (≤ 3–4 levels). For very deep or often-queried trees, consider a\nclosure table or path enumeration strategy to avoid recursive queries.\n",{"id":300,"difficulty":35,"q":301,"a":302},"ef-alternate-keys","What is the difference between a primary key and an alternate key in EF Core?","A **primary key** (`HasKey`) is the entity's identity — one per entity. An\n**alternate key** (`HasAlternateKey`) is an additional unique column that other\nentities can reference as a foreign key.\n\n```csharp\npublic class Product\n{\n    public int Id { get; set; }       \u002F\u002F PK\n    public string Sku { get; set; } = \"\"; \u002F\u002F alternate key — unique, referenced externally\n    public string Name { get; set; } = \"\";\n}\n\npublic class OrderItem\n{\n    public int Id { get; set; }\n    public string ProductSku { get; set; } = \"\"; \u002F\u002F FK pointing to Product.Sku (not PK)\n    public Product Product { get; set; } = null!;\n}\n\n\u002F\u002F Configuration:\nmodelBuilder.Entity\u003CProduct>()\n    .HasAlternateKey(p => p.Sku); \u002F\u002F creates UNIQUE constraint on Sku\n\nmodelBuilder.Entity\u003COrderItem>()\n    .HasOne(i => i.Product)\n    .WithMany()\n    .HasForeignKey(i => i.ProductSku)\n    .HasPrincipalKey(p => p.Sku); \u002F\u002F FK targets the alternate key, not PK\n\n\u002F\u002F Composite alternate key:\nmodelBuilder.Entity\u003CProduct>()\n    .HasAlternateKey(p => new { p.Brand, p.ModelNumber });\n```\n\nAlternate keys differ from `HasIndex(...).IsUnique()`:\n- Alternate keys can be referenced by FKs; unique indexes cannot.\n- Both add a UNIQUE constraint to the schema.\n\n**Rule of thumb:** Use alternate keys when an external system references your entity\nby a natural key (SKU, ISBN, slug). Use unique indexes for uniqueness constraints\nthat don't need to be referenced by FKs.\n",{"id":304,"difficulty":96,"q":305,"a":306},"ef-table-per-hierarchy","What are EF Core inheritance mapping strategies and when do you use each?","EF Core supports three strategies for mapping class hierarchies to relational tables.\nThe strategy affects schema shape, query performance, and null handling.\n\n```csharp\n\u002F\u002F Base entity:\npublic abstract class Payment\n{\n    public int Id { get; set; }\n    public decimal Amount { get; set; }\n}\npublic class CardPayment : Payment { public string Last4 { get; set; } = \"\"; }\npublic class BankPayment : Payment { public string IBAN  { get; set; } = \"\"; }\n\n\u002F\u002F === 1. Table-Per-Hierarchy (TPH) — EF Core default ===\n\u002F\u002F One table, Discriminator column per row:\n\u002F\u002F Payments: Id | Amount | Discriminator | Last4 | IBAN\nmodelBuilder.Entity\u003CPayment>()\n    .HasDiscriminator\u003Cstring>(\"Discriminator\")\n    .HasValue\u003CCardPayment>(\"Card\")\n    .HasValue\u003CBankPayment>(\"Bank\");\n\u002F\u002F Pro: no joins; Con: sparse nullable columns\n\n\u002F\u002F === 2. Table-Per-Type (TPT) — each type has its own table ===\nmodelBuilder.Entity\u003CCardPayment>().ToTable(\"CardPayments\"); \u002F\u002F separate table\nmodelBuilder.Entity\u003CBankPayment>().ToTable(\"BankPayments\");\n\u002F\u002F Pro: normalised, no nulls; Con: JOIN on every query\n\n\u002F\u002F === 3. Table-Per-Concrete-Type (TPC) — EF Core 7+ ===\nmodelBuilder.Entity\u003CCardPayment>().UseTpcMappingStrategy();\nmodelBuilder.Entity\u003CBankPayment>().UseTpcMappingStrategy();\n\u002F\u002F Each concrete type gets a full table with all columns (no FK to base table)\n\u002F\u002F Pro: no joins, normalised; Con: queries over base type need UNION ALL\n\n\u002F\u002F Querying polymorphically works the same regardless of strategy:\nvar allPayments = await _db.Set\u003CPayment>().ToListAsync();\nvar cardPayments = await _db.Set\u003CCardPayment>().ToListAsync();\n```\n\n**Rule of thumb:** Start with TPH — it's the default, simplest, and fastest for\nsmall hierarchies. Use TPT when nullable columns become a schema problem. Use TPC\n(EF Core 7+) for separate tables with no JOINs on concrete-type queries.\n",{"id":308,"difficulty":96,"q":309,"a":310},"ef-shadow-properties","What are shadow properties in EF Core and how do you use them for auditing?","**Shadow properties** exist in the EF Core model and database schema but are NOT\npresent on the entity class. They're useful for auditing, tenancy, and soft-delete\nfields you don't want to expose in the domain model.\n\n```csharp\n\u002F\u002F Define a shadow property in OnModelCreating:\nmodelBuilder.Entity\u003COrder>()\n    .Property\u003CDateTime>(\"CreatedAt\")   \u002F\u002F no matching property on Order class\n    .HasDefaultValueSql(\"GETUTCDATE()\");\n\nmodelBuilder.Entity\u003COrder>()\n    .Property\u003Cstring>(\"CreatedBy\")\n    .HasMaxLength(256);\n\n\u002F\u002F Read and write shadow properties via Entry:\nvar order = new Order { Total = 99.99m };\n\n_db.Entry(order).Property(\"CreatedBy\").CurrentValue = \"alice@example.com\";\n_db.Orders.Add(order);\nawait _db.SaveChangesAsync();\n\n\u002F\u002F Read shadow property from a tracked entity:\nvar createdAt = (DateTime)_db.Entry(order).Property(\"CreatedAt\").CurrentValue!;\n\n\u002F\u002F Filter by a shadow property in a query:\nvar aliceOrders = await _db.Orders\n    .Where(o => EF.Property\u003Cstring>(o, \"CreatedBy\") == \"alice@example.com\")\n    .ToListAsync();\n\n\u002F\u002F Use in SaveChangesInterceptor for automatic auditing:\nforeach (var entry in db.ChangeTracker.Entries\u003COrder>())\n{\n    if (entry.State == EntityState.Added)\n        entry.Property(\"CreatedAt\").CurrentValue = DateTime.UtcNow;\n}\n```\n\n**Rule of thumb:** Use shadow properties for cross-cutting metadata (audit timestamps,\ntenant ID, row version) that shouldn't pollute the domain model. For shared auditing\nacross many entities, combine shadow properties with a `SaveChangesInterceptor`.\n",{"id":312,"difficulty":96,"q":313,"a":314},"ef-table-splitting","What is table splitting in EF Core and when should you use it?","**Table splitting** maps multiple entity types to a single database table. It's\nthe inverse of owned entities — useful when you want to load a \"lightweight\" view\nof a table by default and load the heavy columns separately on demand.\n\n```csharp\n\u002F\u002F Split a table into a lightweight head and a heavy detail entity:\npublic class OrderSummary\n{\n    public int Id { get; set; }\n    public string Status { get; set; } = \"\";\n    public decimal Total { get; set; }\n    public OrderDetail Detail { get; set; } = null!; \u002F\u002F navigation to same table\n}\n\npublic class OrderDetail\n{\n    public int Id { get; set; }         \u002F\u002F same PK — shared with OrderSummary\n    public string Notes { get; set; } = \"\";\n    public byte[]? AttachmentData { get; set; } \u002F\u002F large column — only loaded when needed\n    public OrderSummary Summary { get; set; } = null!;\n}\n\n\u002F\u002F Map both entities to the same table:\nmodelBuilder.Entity\u003COrderSummary>().ToTable(\"Orders\");\nmodelBuilder.Entity\u003COrderDetail>().ToTable(\"Orders\");\n\n\u002F\u002F Configure the 1:1 relationship between the two entity \"halves\":\nmodelBuilder.Entity\u003COrderSummary>()\n    .HasOne(s => s.Detail)\n    .WithOne(d => d.Summary)\n    .HasForeignKey\u003COrderDetail>(d => d.Id); \u002F\u002F same PK — required for table splitting\n\n\u002F\u002F Query the lightweight summary — no blob loaded:\nvar summaries = await _db.Set\u003COrderSummary>()\n    .AsNoTracking()\n    .Where(s => s.Status == \"Pending\")\n    .ToListAsync();  \u002F\u002F SELECT Id, Status, Total FROM Orders WHERE Status='Pending'\n\n\u002F\u002F Load the heavy detail only when needed:\nvar detail = await _db.Set\u003COrderDetail>()\n    .AsNoTracking()\n    .FirstOrDefaultAsync(d => d.Id == orderId);  \u002F\u002F includes Notes and AttachmentData\n```\n\nWhen to use table splitting:\n- A table has large or rarely-needed columns (BLOBs, long text) you want to defer.\n- You can't or don't want to physically split the table in the schema.\n- You want a strongly-typed \"projection\" at the entity level.\n\n**Rule of thumb:** Use table splitting when a table has a natural head\u002Fdetail split\nand the detail columns are large and infrequently needed. For most cases, projection\nvia `Select` into a DTO is simpler and doesn't require a second entity class.\n",{"id":316,"difficulty":96,"q":317,"a":318},"ef-concurrency-tokens","How do you handle optimistic concurrency in EF Core?","**Optimistic concurrency** assumes conflicts are rare and detects them at save time\nrather than locking rows. EF Core supports it via **concurrency tokens** (a column\nincluded in `WHERE` clauses on `UPDATE`).\n\n```csharp\n\u002F\u002F Option 1 — RowVersion (SQL Server rowversion \u002F timestamp):\npublic class Product\n{\n    public int Id { get; set; }\n    public string Name { get; set; } = \"\";\n    public int Stock { get; set; }\n\n    [Timestamp]                    \u002F\u002F maps to SQL Server rowversion column\n    public byte[] RowVersion { get; set; } = Array.Empty\u003Cbyte>();\n}\n\n\u002F\u002F EF generates: UPDATE Products SET Stock=@p0 WHERE Id=@id AND RowVersion=@version\n\u002F\u002F If RowVersion changed (another writer), 0 rows affected → EF throws DbUpdateConcurrencyException\n\n\u002F\u002F Option 2 — Concurrency token (works with any column):\npublic class Product\n{\n    [ConcurrencyCheck]\n    public int Stock { get; set; }\n}\n\u002F\u002F EF adds: AND Stock=@originalStock to the WHERE clause\n\n\u002F\u002F Handle the exception:\ntry\n{\n    await _db.SaveChangesAsync();\n}\ncatch (DbUpdateConcurrencyException ex)\n{\n    foreach (var entry in ex.Entries)\n    {\n        var proposed = entry.CurrentValues;    \u002F\u002F what we tried to write\n        var dbValues  = await entry.GetDatabaseValuesAsync(); \u002F\u002F what's in DB now\n\n        \u002F\u002F Option A — keep proposed values (last writer wins):\n        entry.OriginalValues.SetValues(dbValues!);\n\n        \u002F\u002F Option B — reload DB values (first writer wins):\n        await entry.ReloadAsync();\n\n        \u002F\u002F Option C — merge\u002Falert user\n    }\n    await _db.SaveChangesAsync(); \u002F\u002F retry after resolving\n}\n```\n\n**Rule of thumb:** Use `[Timestamp]` \u002F `rowversion` on SQL Server for row-level\noptimistic concurrency — it's automatic and requires no application logic to update.\nHandle `DbUpdateConcurrencyException` explicitly in high-contention paths.\n",{"id":320,"difficulty":35,"q":321,"a":322},"ef-relationship-without-navigation","Can you configure a relationship in EF Core without a navigation property?","Yes. EF Core lets you define foreign keys and relationships **without navigation\nproperties** — useful when you want to enforce referential integrity at the database\nlevel without polluting the domain model with references to unrelated aggregates.\n\n```csharp\n\u002F\u002F Domain model — Order references CustomerId but has no Customer navigation:\npublic class Order\n{\n    public int Id { get; set; }\n    public int CustomerId { get; set; } \u002F\u002F FK column only, no navigation property\n    public decimal Total { get; set; }\n}\n\npublic class Customer\n{\n    public int Id { get; set; }\n    public string Name { get; set; } = \"\";\n    \u002F\u002F No Orders collection navigation — Order is in a different bounded context\n}\n\n\u002F\u002F Configuration — relationship with no navigation properties:\nmodelBuilder.Entity\u003COrder>()\n    .HasOne\u003CCustomer>()             \u002F\u002F no lambda — no navigation on Order\n    .WithMany()                     \u002F\u002F no lambda — no collection on Customer\n    .HasForeignKey(o => o.CustomerId)\n    .IsRequired()\n    .OnDelete(DeleteBehavior.Restrict);\n\n\u002F\u002F EF Core still creates the FK constraint in the schema:\n\u002F\u002F ALTER TABLE Orders ADD CONSTRAINT FK_Orders_Customers_CustomerId\n\u002F\u002F   FOREIGN KEY (CustomerId) REFERENCES Customers(Id)\n\n\u002F\u002F Query using explicit join instead of navigation:\nvar report = await _db.Orders\n    .Join(_db.Set\u003CCustomer>(),\n          o => o.CustomerId,\n          c => c.Id,\n          (o, c) => new { c.Name, o.Total })\n    .ToListAsync();\n```\n\n**Rule of thumb:** Omit navigation properties across aggregate boundaries in DDD\ndesigns. Configure the FK with `HasOne\u003CT>().WithMany()` (no lambda) to enforce\nreferential integrity in the schema while keeping aggregates decoupled in code.\n",{"id":324,"difficulty":35,"q":325,"a":326},"ef-skip-navigations","What are skip navigations in EF Core many-to-many relationships?","**Skip navigations** are the collection properties that link two entities directly\nacross a join table, without exposing the join entity in the domain model. They are\nthe navigations EF Core creates for implicit many-to-many relationships (EF Core 5+).\n\n```csharp\n\u002F\u002F Implicit many-to-many — skip navigations on both sides:\npublic class Student\n{\n    public int Id { get; set; }\n    public string Name { get; set; } = \"\";\n    public ICollection\u003CCourse> Courses { get; set; } = new List\u003CCourse>(); \u002F\u002F skip nav\n}\n\npublic class Course\n{\n    public int Id { get; set; }\n    public string Title { get; set; } = \"\";\n    public ICollection\u003CStudent> Students { get; set; } = new List\u003CStudent>(); \u002F\u002F skip nav\n}\n\n\u002F\u002F EF creates a hidden join table (StudentCourse) with StudentId and CourseId FKs.\n\n\u002F\u002F Add to a many-to-many relationship via the skip navigation:\nvar student = await _db.Students.Include(s => s.Courses).FirstAsync(s => s.Id == 1);\nvar course  = await _db.Courses.FindAsync(10);\nstudent.Courses.Add(course!);          \u002F\u002F inserts into StudentCourse join table\nawait _db.SaveChangesAsync();\n\n\u002F\u002F Remove from the relationship:\nstudent.Courses.Remove(course!);\nawait _db.SaveChangesAsync();          \u002F\u002F deletes from StudentCourse\n\n\u002F\u002F Direct query through the skip navigation:\nvar studentsInCourse = await _db.Courses\n    .Where(c => c.Id == 10)\n    .SelectMany(c => c.Students)       \u002F\u002F expands through the join table\n    .AsNoTracking()\n    .ToListAsync();\n\u002F\u002F SQL: SELECT s.* FROM Students s\n\u002F\u002F      INNER JOIN StudentCourse sc ON sc.StudentsId = s.Id\n\u002F\u002F      WHERE sc.CoursesId = 10\n\n\u002F\u002F Inspect the underlying join entity type (EF manages it internally):\nvar joinEntity = modelBuilder.Entity\u003CStudent>()\n    .HasMany(s => s.Courses)\n    .WithMany(c => c.Students)\n    .UsingEntity(j => j.ToTable(\"StudentCourse\")); \u002F\u002F rename the join table\n```\n\n**Rule of thumb:** Use skip navigations (implicit many-to-many) when the join table\nis a pure relationship with no extra columns. The moment you need metadata on the\njoin (e.g., `EnrolledAt`, `Grade`), switch to an explicit join entity.\n",{"id":328,"difficulty":43,"q":329,"a":330},"ef-required-vs-optional-relationships","What is the difference between a required and an optional relationship in EF Core?","A **required relationship** means the dependent entity must have a principal —\nthe foreign key is `NOT NULL`. An **optional relationship** allows the FK to be\n`NULL`, meaning the dependent can exist without a principal.\n\n```csharp\n\u002F\u002F Required relationship — FK is NOT NULL:\npublic class Order\n{\n    public int Id { get; set; }\n    public int CustomerId { get; set; }       \u002F\u002F non-nullable int → required\n    public Customer Customer { get; set; } = null!;\n}\n\n\u002F\u002F Fluent API — explicit required:\nmodelBuilder.Entity\u003COrder>()\n    .HasOne(o => o.Customer)\n    .WithMany(c => c.Orders)\n    .HasForeignKey(o => o.CustomerId)\n    .IsRequired();                            \u002F\u002F NOT NULL in schema\n\u002F\u002F EF default for non-nullable FK types: already required by convention.\n\n\u002F\u002F Optional relationship — FK is nullable:\npublic class Order\n{\n    public int Id { get; set; }\n    public int? SupplierId { get; set; }      \u002F\u002F nullable int → optional\n    public Supplier? Supplier { get; set; }   \u002F\u002F nullable reference navigation\n}\n\n\u002F\u002F Fluent API — explicit optional:\nmodelBuilder.Entity\u003COrder>()\n    .HasOne(o => o.Supplier)\n    .WithMany(s => s.Orders)\n    .HasForeignKey(o => o.SupplierId)\n    .IsRequired(false);                       \u002F\u002F NULL allowed in schema\n\n\u002F\u002F Cascade delete default differs:\n\u002F\u002F Required → EF default is Cascade (delete dependents when principal deleted)\n\u002F\u002F Optional → EF default is SetNull (null out the FK when principal deleted)\n\n\u002F\u002F Practical consequence for loading:\nvar order = await _db.Orders.Include(o => o.Supplier).FirstAsync(o => o.Id == 1);\nif (order.Supplier is not null) \u002F\u002F must null-check optional navigation\n    Console.WriteLine(order.Supplier.Name);\n```\n\n**Rule of thumb:** Make a relationship required when the dependent has no business\nmeaning without the principal (order must have a customer). Make it optional when\nthe principal can legitimately be absent (order might not have a supplier yet).\nReflect this in the FK nullability and reference navigation nullability in C#.\n",{"description":32},"EF Core relationships interview questions — one-to-many, many-to-many, cascade delete, owned entities, shadow properties, and concurrency tokens.","dotnet\u002Fentity-framework\u002Frelationships","Ln3w7lvTnOuyFOadatsHqJU8IuZnrM3K7T35Sy242h8",1782244097522]