Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use only one instance of a tracked immutable entity #24923

Closed
robertlarkins opened this issue May 18, 2021 · 3 comments
Closed

How to use only one instance of a tracked immutable entity #24923

robertlarkins opened this issue May 18, 2021 · 3 comments

Comments

@robertlarkins
Copy link

This question is about what or whether there is a good way of telling the context to use only a particular instance of an immutable entity in the context, as it is producing an EF Core instance of entity type cannot be tracked error, I know there are a number of issues pertaining to this, but havn't seen a good solution on how to avoid this when using statically defined entities.

(I suspect this relates to this issue: #20124)

I have these two entities (using vkhorikovs Entity class):

public class AppointmentStatus : Entity<int>
{
	public static readonly AppointmentStatus Planned = new(1, "Planned");
	public static readonly AppointmentStatus Occurring = new(2, "Occurring");
	public static readonly AppointmentStatus Finished = new(3, "Finished");

	protected AppointmentStatus()
	{
	}

	private AppointmentStatus(int id, string name) : base(id)
	{
		Name = name;
	}

	public string Name { get; } = string.Empty;

	public static List<AppointmentStatus> GetAll()
	{
		return new()
		{
			Planned,
			Occurring,
			Finished
		};
	}
}

and

public class Appointment : Entity<int>
{
	public Appointment(AppointmentStatus appointmentStatus)
	{
		AppointmentStatus = appointmentStatus;
	}

	protected Appointment()
	{
	}

	public AppointmentStatus AppointmentStatus { get; private set; } = null!;

	public void SetStatus(AppointmentStatus appointmentStatus)
	{
		AppointmentStatus = appointmentStatus;
	}
}

From reading and my (limited) understanding what is happening is some query pulls the static defined variable into the context (say AppointmentStatus.Finished in this case), such as when getting all the Appointments, so this become the instance known to the context, but when updating an appointment to AppointmentStatus.Finished from the static reference in AppointmentStatus, this becomes a second instance tracked by the context. EF then sees these as two separate instances for the same thing (even though they are the same, and immutable), as EF determines equivalency by reference equals.

This is the solution with tests to show this in action: https://github.com/robertlarkins/efcore-cannot-track-entity-issue

What would be the best way of telling the context to only use one of the instances and ignore the other?

EF Core version: 5.0.5
Database provider: Microsoft.EntityFrameworkCore.InMemory and Microsoft.EntityFrameworkCore.Sqlite (both v5.0.5) - would ideally be using this against NpgSql, but for the demo solution using inmemory.
Target framework: .NET 5.0
Operating system: Windows 10
IDE: Visual Studio 2019 16.9.5

@TonyValenti
Copy link

I don't think you can do what you're wanting. However, you might consider creating extension methods like IsPlanned or IsOccurring that determine whether an instance matches what you want.

Alternatively, it looks like you're basically just storing an enum in the database. In that case, why not just store it as an enum?

@AndriySvyryd
Copy link
Member

@robertlarkins As you've said #20124 should enable this scenario

@robertlarkins
Copy link
Author

robertlarkins commented May 19, 2021

Thanks for you suggestions @TonyValenti, in this case I was following articles like this

I guess at this stage I use some work arounds and hope that EFCore gets this capability in the not to distant future.

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants