Custom property access patterns
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 20/100
Research direction
Start by tracing the hardcoded property discovery, value-getting, value-setting, materialization, and change-tracking assumptions described in the issue, then compare them with the dynamic models discussion in issue #2282. Done would require a settled design for registering custom discovery and access patterns, including getter and setter behavior for extension properties or property bags.
Written by the indexing model from the issue text.
Description
Currently EF uses some hardcoded assumptions involving properties and fields to:
- Decide whether a property with a specific name and type exist on an entity
- Get the property's value for change tracking and persistence purposes
- Set the property's value during materialization or fixup
The article at http://www.codeproject.com/Articles/399932/Extension-Properties-Revised describes an example a non-standard property access pattern that EF could support in the future.
Another much more well-known pattern I expect many customers to want to use is to store property values into an property bag (e.g. IDictionary<string, object>) in the entity itself.
It seems to me that the first step to support patterns like those would be to refactor the current assumptions into a default property access pattern and to allow for alternative property access patterns to be registered with EF. I.e. you would need to be able to tell EF that for a specific property you want it to use specific expressions for getting and setting the value, e.g. the default property access pattern using an actual property could be expressed somewhat like this (I have taken some shortcuts: made up a couple of method names and assumed no field access):
modelBuilder.Entity<Product>().Property<DateTime>("Expiration")
.Getter(p => p.Expiration)
.Setter((p, value) => p.Expiration = value);
To register an "extension property" as described in the article linked at the beginning, you would need to write something like this:
modelBuilder.Entity<Product>().Property<DateTime>("Expiration")
.Getter(p => p.GetValue<DateTime>("Expiration"))
.Setter((p, value) => p.SetValue("Expiration", value));
For an property bag you would write something like this:
modelBuilder.Entity<Product>().Property<DateTime>("Expiration")
.Getter(p => (DateTime)p.ExtendedProperties["Expiration"])
.Setter((p, value) => p.ExtendedProperties["Expiration"] = value);
Then the next step would be to make all of this more usable by figuring out a way to write it in a more generic way, so that end uses wouldn't need to repeat themselves. E.g. for illustration, let's say that property access patterns could be represented by a class (which probably implements some interface), then a user could write something like this:
modelBuilder.Entity<Product>().Property<DateTime>("Expiration").AccessAs<ExtensionProperty>();
Custom property access patterns like this could generate expressions with additional logic, e.g. to throw a nicer exception if a value of an invalid type is encountered, to take advantage of fields, etc.
Discovery
I would expect that in most cases the motivation to use a pattern like this has to do with needing an entity that is more loosely typed (see support for dynamic models at https://github.com/aspnet/EntityFramework/issues/2282). For those cases the entity by design does not contain reflection information about the property and hence the property has to be explicitly declared in the model.
Yet, it is possible that in certain scenarios the entity type could contain information about the property, but encoded in a different way from what a standard property would look like to reflection. These scenarios could be handled by allowing customizing property discovery logic.
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 134
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from dotnet/efcore
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
-
customer-reported
Difficulty 5/5 Over a week Newbie friendliness 38/100
-
area-cosmos area-vector-search
Difficulty 5/5 Over a week Newbie friendliness 25/100
-
area-cosmos
Difficulty 5/5 Over a week Newbie friendliness 25/100
-
area-tools needs-design
Difficulty 4/5 3-5 days Newbie friendliness 25/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
-
:watch: Not Triaged 11.0 fundamentals/subsvc
Difficulty 2/5 1-3 hours Newbie friendliness 92/100
dotnet/AspNetCore.Docs#37699 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
SubtitleEdit/subtitleedit#15108 · 1 comment ·
-
area/docs-content Bug pulumi/docs
Difficulty 1/5 1-3 hours Newbie friendliness 94/100
-
agentic-workflows untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 76/100