Consider single-responsibility-principle for AsNoTracking() with fix-ups

Open
#11,227 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Stale
Tech stack
csharp
Domain
databases

Research direction

Start with the provided C# reproduction and the tracking documentation linked in the issue, then compare the behavior described in issue #10603. The work is not ready for a newcomer until the desired fix-up semantics are decided between changing AsNoTracking() and adding a separate or configurable option; completion would require implementing that agreed behavior and verifying both fix-up cases.

Written by the indexing model from the issue text.

Description

area-query

Nowadays (efcore 2.0 and 2.1-pre1), AsNoTracking() does not do fix-ups for reference-properties (practically) and, as far as I know, this is considered as a bug and going to be fixed in 2.1 (issue #10603).
Some time ago it did, and some people complained that they actually do not want it happen (see docs comments at the bottom: https://docs.microsoft.com/en-us/ef/core/querying/tracking).
So I think, AsNoTracking() either should not care about Fix-ups and delegate it to other method like SkipFixups(), or should be configurable - AsNoTracking(bool fixups=true), because most scenarios need fix-ups, but there are obviously exist some where they are extremly undesirable.

Added:
proof of not fixing-up

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;

namespace ConsoleApp1
{

    [Table("parents")]
    public class Parent
    {
        public int id { get; set; }
        public string name { get; set; }
        public List<Child> Children { get; set; }
    }

    [Table("children")]
    public class Child
    {
        public int id { get; set; }
        public string name { get; set; }
        [Required]
        public Parent parent { get; set; }
    }

    class MyDbContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
            optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TMP-C461BBF28F0C;Trusted_Connection=True;MultipleActiveResultSets=true");
        }
        public DbSet<Parent> Parents { get; set; }
        public DbSet<Child> Children { get; set; }
    }


    class Program
    {
        static void Main(string[] args)
        {
            using(MyDbContext db = new MyDbContext()){
				if (!db.Parents.Any())
				{
					Parent category1 = db.Add(new Parent { name = "p1" }).Entity;
					db.Add(new Child {parent=category1, name = "c11" });
					db.Add(new Child {parent=category1, name = "c12"});
					Parent category2 = db.Add(new Parent { name = "p2" }).Entity;
					db.Add(new Child { parent = category2, name = "c21" });
					db.Add(new Child { parent = category2, name = "c22" });
					db.SaveChanges();
				}
			}
            using(MyDbContext db = new MyDbContext()){
				db.Parents.Load();
				var c11 = db.Set<Child>().AsNoTracking().First(x => x.name == "c11");
				var c12 = db.Set<Child>()               .First(x => x.name == "c12");
				Console.WriteLine("parent={0}", c11.parent); //returns null
				Console.WriteLine("parent={0}", c12.parent); //not null
			}
        }
    }
}

Dominant language
C#
Stars
14.8k
Forks
3.4k
Avg merge
2d 5h
Merged PRs (30d)
134

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dotnet/efcore

All issues in dotnet/efcore

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.