[{"data":1,"prerenderedAt":110},["ShallowReactive",2],{"qa-\u002Fdotnet\u002Fentity-framework\u002Frelationships":3},{"page":4,"siblings":94,"blog":107},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"questionsCount":85,"related":86,"seo":87,"seoDescription":88,"stem":89,"subtopic":6,"topic":90,"topicSlug":91,"updated":92,"__hash__":93},"qa\u002Fdotnet\u002Fentity-framework\u002Frelationships.md","Relationships",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md",".NET Core","dotnet",{},true,4,"\u002Fdotnet\u002Fentity-framework\u002Frelationships",[23,28,32,36,40,44,48,52,56,61,65,69,73,77,81],{"id":24,"difficulty":25,"q":26,"a":27},"ef-one-to-many","easy","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":29,"difficulty":14,"q":30,"a":31},"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":33,"difficulty":14,"q":34,"a":35},"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":37,"difficulty":25,"q":38,"a":39},"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":41,"difficulty":14,"q":42,"a":43},"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":45,"difficulty":14,"q":46,"a":47},"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":49,"difficulty":14,"q":50,"a":51},"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":53,"difficulty":14,"q":54,"a":55},"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":57,"difficulty":58,"q":59,"a":60},"ef-table-per-hierarchy","hard","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":62,"difficulty":58,"q":63,"a":64},"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":66,"difficulty":58,"q":67,"a":68},"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":70,"difficulty":58,"q":71,"a":72},"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":74,"difficulty":14,"q":75,"a":76},"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":78,"difficulty":14,"q":79,"a":80},"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":82,"difficulty":25,"q":83,"a":84},"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",15,null,{"description":11},"EF Core relationships interview questions — one-to-many, many-to-many, cascade delete, owned entities, shadow properties, and concurrency tokens.","dotnet\u002Fentity-framework\u002Frelationships","Entity Framework Core","entity-framework","2026-06-23","Ln3w7lvTnOuyFOadatsHqJU8IuZnrM3K7T35Sy242h8",[95,99,102,106],{"subtopic":96,"path":97,"order":98},"DbContext & DbSet","\u002Fdotnet\u002Fentity-framework\u002Fdbcontext-dbset",1,{"subtopic":100,"path":101,"order":12},"Migrations","\u002Fdotnet\u002Fentity-framework\u002Fmigrations",{"subtopic":103,"path":104,"order":105},"Querying","\u002Fdotnet\u002Fentity-framework\u002Fquerying",3,{"subtopic":6,"path":21,"order":20},{"path":108,"title":109},"\u002Fblog\u002Fdotnet-ef-relationships","Configuring Relationships in EF Core",1782244118870]