-
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
Allow more flexible conditional mapping for TPH and similar #10140
Comments
@Tarig0 The normal pattern for TPH mapping in EF creates the discriminator property as a shadow property, and also marks it as read-only-after-save, both of which mean that to get to a place where the value can be modified arbitrarily requires some deviation from the norm. This is balanced with EF Core not blocking certain things that can be useful if you know what you are doing--for example, it's sometimes useful to be able to save a different discriminator value to cause a type change, but it's easy to shoot yourself in the foot if you're not careful. To your first point, we could do some extra validation to prevent arbitrary values being saved, probably with some way to override this if needed, but at this point we don't think there is enough return on investment and it could also have perf implications for the update pipeline. To your second point, we have talked a lot in the past about making the discriminator pattern just a specific case of more general conditional mapping, which would allow things like null/not null to be used. Since we don't seem to have an issue for this in the backlog I will re-purpose this issue for those cases. Couple of questions for you:
|
The case I was stretching for was to allow the end user to create new "types" at runtime which would act as the base type, until I could extend it later. I would most likely end up using an enum, if I have to give a defined list at compile time, and have the base class be the default type. This would restrict me from doing things accidentally, and my previous case but I'm OK with adding a single line of code to a release/patch. possible syntax for explicit list of discriminators. typeEnum Type {get;set}
modelBuilder.Entity<BaseClass>().HasDiscriminator(e=>e.Type)
.HasValue<ExplicitChild>(typeEnum.ExplicitChild)
.HasValue<BaseClass>(new [] {typeEnum.Child1,typeEnum.Child2}) // or params |
on your point on what would I expect when creating a base type, I would expect the discriminator to have to be explicitly defined, before attaching the entity. Another option is to add a fluent function to the hasdiscriminator path, something like "HasDefaultDiscriminator" or have hasvalue have the overload that takes an ienumerable require a T param to be passed for the default typeEnum Type {get;set}
modelBuilder.Entity<BaseClass>().HasDiscriminator(e=>e.Type)
.HasValue<ExplicitChild>(typeEnum.ExplicitChild)
.HasValue<BaseClass>(typeEnum.Child1,typeEnum.Child2)
.HasDefaultDiscriminator<BaseClass>(typeEnum.Child1);
modelBuilder.Entity<BaseClass>().HasDiscriminator(e=>e.Type)
.HasValue<ExplicitChild>(typeEnum.ExplicitChild)
.HasValue<BaseClass>(default:typeEnum.Child1, typeEnum.Child1,typeEnum.Child2) |
I just realized there is nothing stopping me from generating the explicit list at dbcontext construct time, or at program start time. I would have to gather the data either from configuration or manually query the database. Either way it would allow me to do things with wild cards out side of EFcores engine. |
Would this allow a discriminator to be configured across multiple columns, i.e. a composite discriminator? |
Not with how it's been discussed, think that would be in an issue for type conversion. |
Consider the case in #14601 when working on this. |
See also multiple discriminator values in #15365 |
Is there some timeline when this is going to be added? |
@schrufygroovy If an issue is in the backlog it means that it hasn't been considered for any release yet. A possible implementation is to have the discriminator typed as |
Are there any workarounds to assign multiple discriminator values for a single derived type? |
@gojanpaolo The only "work around" is to create the classes for each discriminator value. |
During a team meeting today we came up with a work-around. You can use FromSql to remap your table in a way to make it look like known values only. context.BaseType.FromSql(
"Select Id,... /*other columns */,
CASE
WHEN Discriminator = N'UnknownValue' THEN N'DerivedTypeValue'
ELSE Discriminator
END AS Dicriminator
FROM BaseTypeTable"); |
👍 nice fromsql find better yet you can move the sql to a sproc to be able to do updates without updating the code |
@AndriySvyryd how about something like this cosmos-specific-model-customization HasNoDiscriminator i tried to use this on my case "SecurityUser" model but got the following exception
|
@alfred-zaki If you are using TPH you need some discriminator |
@AndriySvyryd is there any workaround for my situation using 3.1.7? Seems like this feature not going to be worked on anytime soon if ever! |
@alfred-zaki unfortunately no. You need to declare different classes for each discriminator. |
@alfred-zaki You could map only one class to the table that will contain all the corresponding properties. Alternatively you could use table sharing and map the extra columns to an owned type. |
@AndriySvyryd |
I have the following model
I am able to create a BaseType with a type value as "Implicit Child" and save it to the database, but when retrieving the information I can not get a reference to the "Implicit Child."
This is caused by the discriminator column being present in the where clause at all times.
I would expect one of the following
Further technical details
EF Core version: 2.0.0
Database Provider: SqlLite, MSSql
Operating system: Windows 10
IDE:Visual Studio 2017
The text was updated successfully, but these errors were encountered: