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

TPH does not support immutable discriminator properties #4650

Closed
jnm2 opened this issue Feb 26, 2016 · 7 comments
Closed

TPH does not support immutable discriminator properties #4650

jnm2 opened this issue Feb 26, 2016 · 7 comments

Comments

@jnm2
Copy link

jnm2 commented Feb 26, 2016

I have the following model:

abstract class BaseClass
{
    public abstract SubclassTypeEnum Type { get; }
}

class Subclass1 : BaseClass
{
    public override SubclassTypeEnum Type => SubclassTypeEnum.Subclass1;
}

When loading from the database:

No backing field could be discovered for property 'Subclass1.Type' and the property does not have a setter. Either use a backing field name that can be matched by convention, annotate the property with a backing field, or define a property setter.

This should not be a problem. If EF cannot find a way to set the value of Type, it should simply compare it to see if it already equals the value it's trying to set. The value of Type has already been taken into account by selecting the Subclass1 type.

If the discriminator property is expressed in the CLR model, it would be unusual for a model not to initialize a discriminator property. Indeed it seems counter-intuitive for the model to allow the property to be mutable. For my case, there's no reason to add a backing field on every instance and add the possibility of data corruption when the value is known statically by the subclass. Even if the setter is available it may be better simply to skip the set, check the property value and throw an error if the constructor didn't initialize the property with the expected discriminator value.

Also, EF6 supports this scenario and it's a good precedent.

Full repro code.

(These issues look related but I don't think this is a duplicate.)

@rowanmiller
Copy link
Contributor

This will be enabled by our "Flexible mapping to CLR types and members" feature (#240). That would allow you to specify how the value is get/set from the property - allowing you to no-op the property set if you know it's going to be the right value.

If EF cannot find a way to set the value of Type , it should simply compare it to see if it already equals the value it's trying to set.

Materialization code is very perf sensitive, so we don't do checks like this (they tend to slow things down a lot).

@rowanmiller
Copy link
Contributor

BTW in the meantime the workarounds would be to add a field or add a private setter.

@jnm2
Copy link
Author

jnm2 commented Feb 29, 2016

If it's a perf-sensitive thing, why not skip the set altogether? That would be ideal for both perf and enforcing correctness. You don't want people relying on EF to set the discriminator value, so skipping the set would encourage better coding (= read only discriminator so that it can never conflict with the subclass type).

@rowanmiller
Copy link
Contributor

The reason we set it is there is no guarantee that the entity is setting it to the right value itself (as yours does). It's one of those things where "the right thing to do" varies greatly depending on who you talk to, so we tend to leave it as flexible as any other property you would map to. To be clear, we definitely want to support your scenario (for more than just discriminator properties), it's just not done yet.

@jnm2
Copy link
Author

jnm2 commented Feb 29, 2016

Thanks for the clarification. I think the pit of success with mutable discriminators is to discourage them and to be strict checking them. I'm curious what the discussion has been so far (in what scenarios is a mutable discriminator necessary or a good design?), but since I won't have mutable discriminators in my code I won't care. I'll just wait until I don't need a private setter anymore and be happy.

@rowanmiller
Copy link
Contributor

think the pit of success with mutable discriminators is to discourage them and to be strict checking them. I'm curious what the discussion has been so far (in what scenarios is a mutable discriminator necessary or a good design?),

The default behavior with EF is to have discriminators as shadow properties... so there isn't even a property in your class at all. To me this makes the most sense, because there are already first class ways of reasoning about types in code (GetType(), as, is, OfType<T>(), IsAssignableFrom etc.). To me, the fact that you need a column in the database to differentiate between types is a characteristic of a relational database and shouldn't impact your entity classes.

@jnm2
Copy link
Author

jnm2 commented Feb 29, 2016

That is an excellent point which I had not considered: simply leaving the discriminator column out of the model. I do not like the defaults because I do care about the database schema and byte enums are my favorite way of handling this. But with shadow properties I can have the best of both worlds.

To me, the fact that you need a column in the database to differentiate between types is a characteristic of a relational database and shouldn't impact your entity classes.

Ironically, I'm using separate data and domain models. My domain model uses an enum with a value for each subclass as a sorting technique, since subclasses are sorted by date and type. So the entity (domain) model already has the enum, but for the relational (data) model I don't actually want the discriminator column on the model classes because it's redundant and meaningless on the relational model.

@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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants