-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Enable model-level entity properties to be associated to a backing field but no property getter or setter #4357
Comments
For triage: I am almost sure we said this had to be in the backlog but leaving the milestone empty just in case. |
@divega @rowanmiller @anpete @AndriySvyryd Here is a proposal based on the discussion we had yesterday. Thoughts? .Property(e => e.Id).UseField("_key");
.Property("Id").UseField("_key"); If the property is a CLR property, then this just configures the backing field to use for that property--i.e. it is just fluent API for what we already have. If the property is not a CLR property, then this makes the property always use the field for storage. So it is no longer a shadow property and becomes a mapping to the field. .Property("_key").UseField("_key");
.Property("_key").UseField(); These both do the same thing--the property in our metadata is now named the same as the CLR field. This is functionally the same as the field mapping above. Related to this is #4855 which is about whether to use the property or the backing field directly when accessing properties. Proposal is to have three modes:
If we are preferring properties, then we will use the property getter/setter if available, otherwise fall back to using the field. Likewise, if we are preferring field, then we will use the field unless the field is not specified or cannot be found, in which case we fall back to using the property. The default is PreferFieldForQuery, which matches our current behavior. This mode can be set at the Model, Entity, or Property level: modelBuilder.HasPropertyAccessMode(PreferProperty);
modelBuilder
.Entity<Foo>()
.HasPropertyAccessMode(PreferProperty);
modelBuilder
.Entity<Foo>()
.Property(e => e.Id)
.HasPropertyAccessMode(PreferProperty); So if you map all your fields and use PreferField on the model, then we will never access your properties and you get complete mapping to backing fields. Very open to suggestions for naming. |
Looks good. Question: When there is no CLR property "_key", will .Property("_key"); add a field-backed property if a matching field is found? Perhaps HasPropertyAccessMode -> UsePropertyAccessMode |
@anpete Depends whether or not we think that any significant number of people are currently doing this and have working apps with shadow state properties. Safest thing is to not do it. Best experience assuming we think we can make the break is to do it. |
@ajcvickers Could be a feature flag, too. |
Can we have a shortcut syntax that infers, based on a convention, the name of the backingField to avoid a bunch of magic strings e.g.
infers to use a backing field called In this case the convention uses by default a field which is named _{camelCasedPropertyName}. It would be even nicer if we can replace this convention with a custom one. |
@ilmax EF Core already does that. |
@ajcvickers nice 😄, sorry for asking |
At first glance the proposal looks good and it seems that having
I have a few ideas of tweaks we could try on this proposal but I think it would be more productive to chat in person. Orthogonal to that:
|
Notes from triage // Configure a field (will be used during materialization but not fix-up etc.)
modelBuilder
.Entity<Foo>()
.Property(e => e.Id)
.HasField("_id");
// Configure a field and enforce it is always used
modelBuilder
.Entity<Foo>()
.Property(e => e.Id)
.HasField("_id")
.UsePropertyAccessMode(PropertyAccessMode.Field);
// Skip using field even if it was found by convention
modelBuilder
.Entity<Foo>()
.Property(e => e.Id)
.UsePropertyAccessMode(PropertyAccessMode.Property);
// Enforce that a field was found and should be used
modelBuilder
.Entity<Foo>()
.Property(e => e.Id)
.UsePropertyAccessMode(PropertyAccessMode.Field);
// Stop using fields even where they were found by convention
modelBuilder.UsePropertyAccessMode(PropertyAccessMode.Property)
// Enforce that all access goes thru fields (except shadow properties)
modelBuilder.UsePropertyAccessMode(PropertyAccessMode.Field)
PropertyAccessMode.Field
PropertyAccessMode.FieldDuringConstruction
PropertyAccessMode.Property |
Also note that an atribute would allow you to use |
Currently the string version of
Property<T>()
can only be used to create a shadow state property. This issue is about enabling declaring model-level properties on CLR types that are backed by a field but don't have a property getter or setter. E.g. assuming a fluent API for setting the "BackingField" annotation, we could enable code like this:The text was updated successfully, but these errors were encountered: