Changes are not tracked when using projections in Entity Framework Core 3.1

.net-core c# entity-framework-core

Question

With projections (0 changes):

var changesBefore = Db.ChangeTracker.Entries<OrderLocationEntity>().ToList(); //before change - 0

var orderLocation = Db.OrderLocation.AsTracking().Select(ol => new OrderLocationEntity
{
    Id = ol.Id,
    Address = ol.Address,
    City = ol.City,
    Created = ol.Created,
    OrderId = ol.OrderId,
    Zip = ol.Zip
}).First();

orderLocation.Address = "address";

var changesAfter = Db.ChangeTracker.Entries<OrderLocationEntity>().ToList(); //after change - 0

Without projections (1 changes)

var changesBefore = Db.ChangeTracker.Entries<OrderLocationEntity>().ToList(); //before change - 0

var orderLocation = Db.OrderLocation.AsTracking().First();

orderLocation.Address = "address";

var changesAfter = Db.ChangeTracker.Entries<OrderLocationEntity>().ToList(); //after change - 1

Setup

Microsoft.EntityFrameworkCore 3.1.1

Microsoft.EntityFrameworkCore.Sqlite 3.1.1

var options = new DbContextOptionsBuilder<OrderDatabaseContext>()
                .UseSqlite("DataSource=:memory:")
                .Options;

If the result set contains entity types coming out from LINQ composition, EF Core will track them.

Source

https://docs.microsoft.com/en-us/ef/core/querying/tracking

Why are changes not being tracked when using projections?

1
0
1/30/2020 8:55:19 PM

Accepted Answer

Notice "entity types":

If the result set contains entity types coming out from LINQ composition, EF Core will track them.

From the same docs:

If the result set doesn't contain any entity types, then no tracking is done.

Your projection doesn't contain entity types, so changes will not be tracked.

For example if you will introduce property to keep OrderLocationEntity instance, that instance will be tracked by the context

var location = Db.OrderLocation.AsTracking()
    .Select(ol => new OrderLocationEntity
    {
        Id = ol.Id,
        Address = ol.Address,
        City = ol.City,
        Created = ol.Created,
        OrderId = ol.OrderId,
        Zip = ol.Zip,
        Location = ol // entity instance passed to the projected object
    })
    .First();

location.Location.Address = "New Address"; 

Db.ChangeTracker.Entries<OrderLocationEntity>().ToList(); //after change - 1
1
1/30/2020 9:01:49 PM

Popular Answer

Because they do not track them. This was disabled in 3.1 where projects automatically add AsNoTracking.

One more of many many many decisions that can not really be explained and make EfCore 3.1 a product - that can not compete with Ef 6.4.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow