dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.52k stars 3.13k forks source link

Relational: TPT inheritance mapping pattern #2266

Closed satyajit-behera closed 4 years ago

satyajit-behera commented 9 years ago

Even if TPT is considered slow, it is a boon for many real world business scenarios. If implemented properly and well thought of, TPT is not slow for a given need in most of the cases.

If possible, optimization can be done to TPT. But its a very important feature for EF to be accepted for developing DDD applications.

The other method, Composition over Inheritance does not look viable since we cannot use interface property to create our model. Binding to a concrete type takes away the flexibility to customize the models. TPT makes the customization very easy and flexible.

satyajit-behera commented 8 years ago

@rowanmiller I hope, work on this item will start now. Thanks a lot.

robhurd86 commented 7 years ago

+1 vote for TPT. Is there news about when this feature will be released? I read it's high priority.

weitzhandler commented 7 years ago

Is there any temporary workaround to target TPT in EF 7? It's is a mandatory requirement in all of our projects.

sanalbakis commented 7 years ago

@weitzhandler what do you need excatly? Instead of tpt, I made something else in my project. Unfortunately more db connections.

BaseTable: Id, BaseId, XXX, createdbyId, createdDate, ... ChildTable: Id, BaseTableId,YYY

before each insert into ChildTable, I make an insert into BaseTable, get the BaseId, and use it in ChildTable - BaseTableId as foreign-key.

JohnAskewBB commented 7 years ago

TPH will facilitate this if you define a DbSet for each type.

On Oct 20, 2016 7:35 AM, "Shimmy" notifications@github.com wrote:

What I need is pretty simple: -Person (Id, Name) -Employee (Salary) -Customer (Address, Phone)

Should be translated to 3 different tables, with the columns as they appear above.

LOB apps became very time consuming since the death of Silverlight and RIA services. Gosh I miss those days.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/aspnet/EntityFramework/issues/2266#issuecomment-255081370, or mute the thread https://github.com/notifications/unsubscribe-auth/AGafBAQ0XMA4I3f6OiX7oxENsO9DVpLuks5q11IEgaJpZM4EnOQ5 .

JohnAskewBB commented 7 years ago

By contributing to an open source project, writing some SQL, or making multiple queries.

If you want Person as anything other than an abstract type I would stick with TPH for now and just don't look directly at the DB.

Ignorance is bliss

On Oct 20, 2016 7:56 AM, "Shimmy" notifications@github.com wrote:

And how do I retrieve all Persons?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/aspnet/EntityFramework/issues/2266#issuecomment-255085287, or mute the thread https://github.com/notifications/unsubscribe-auth/AGafBMIgqH9nsARxG7ruCBiznHiMz7deks5q11b6gaJpZM4EnOQ5 .

weitzhandler commented 7 years ago

Ignorance is bliss

WOW @JohnAskewBB and you call this ignorance! I'm looking for efficiency. I can write all my queries in direct SQL.

Anyway, I haven't tried this yet, but I'm curious what happens if I make a DbSet<Person> but in the model building stage I mark Employee and Contact to be generated as a table, what would happen then, will they be generated? Can you make this happen, and if yes, can I plug in a convention or some other hack to automate this and fool EF7 to be TPT?

anpete commented 7 years ago

@weitzhandler One way might be to map via TPH to a database view. Then use something like INSTEAD OF triggers to send the updates to the actual target tables.

JohnAskewBB commented 7 years ago

I don't think that will work. You would end up being able to save the same entity in either the Person table or the Contact table for example. You could give it the same id but you would need to keep the records in sync somehow. and you wouldn't be able to cast a Person to a Contact. You would have to get it from Contact by id.

On Oct 20, 2016 7:56 PM, "Shimmy" notifications@github.com wrote:

WOW @JohnAskewBB https://github.com/JohnAskewBB and you call this ignorance! I'm looking for efficiency. I can write all my queries in direct SQL.

Anyway, I haven't tried this yet, but I'm curious what happens if I make a DbSet but in the model building stage I mark Employee and Contact to be generated as a table, what would happen then, will they be generated? Can you make this happen, and if yes, can I plug in a convention or some other hack to automate this and fool EF to be TPT?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/aspnet/EntityFramework/issues/2266#issuecomment-255259526, or mute the thread https://github.com/notifications/unsubscribe-auth/AGafBIlNj5AeqoD-OWEzkZGpskR-oym-ks5q1_-ZgaJpZM4EnOQ5 .

satyajit-behera commented 7 years ago

@rowanmiller Hope this is taken up soon and allow everyone to move to DOTNET CORE faster. This is one of the important feature holding us back. No other alternative working out as a replacement for this feature. Thanks.

rowanmiller commented 7 years ago

@weitzhandler it's not on the plan for a release as yet. At this stage, that means it would be post 2.0

jimmymain commented 7 years ago

If anyone want's a workaround for EF6 that works well, I have used this https://github.com/mrahhal/MR.AspNet.Identity.EntityFramework6

it's a drop in replacement that allows ASP.NET core + EF6 with the new identity management for ASP.NET core. if you're starting a new project and want to use EF6 until such time as EF7 is mature enough, this project will help - assuming to want to leverage ASP.NET identity.

if you wanted to start migrating (re-write) an existing MVC5 application to MVC6 but need EF6 it's also a great solution.

Obviously the caveat remains that you need to use the full framework, you cannot deploy to core only.

jimmymain commented 7 years ago

Have you all seen this? https://www.infoq.com/news/2017/05/ASPNET-Core-2?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global

It would appear that entity framework 6 on dotnet core is going to be unsupported pretty soon. This makes all the work we have been doing in porting to dotnet core in jeopardy. It also makes TPT vastly more urgent than it used to be.

What's the status of these advanced features on EF core? There's little or no communication. It's been two years or more since this issue was logged.

What does POST 2 mean? 2018? 2019? 2020?

We might have to consider back porting our dotnet core web sites back to ASP.NET / MVC 5 just to keep them working?

weitzhandler commented 7 years ago

@jimmymain that's upsetting. Probably the only reason keeping me away from EF Core is TPT and ComplexTypes, that's two features we can't live without.
Imagine a scenario of:

Mandatory is obtaining a searchable DbSet<Vehicle>. TPH and TPC make no sense for me in here. Lack of Complex Types makes a mess in the code-first models. Hearing the EF6 is going to be kicked out of .NET Core before EF Core provides answer to those very elementary features, questions the entire advantage of .NET Core in many situations when MVC 5 was robust enough.

soeron commented 7 years ago

+1 For this feature. It is very needed and I think it should have been prioritized much earlier. I really hope to see some action on this for the current 2.0 timeframe. Even some very optimistic and basic functionality can unblock current and new projects to continue development while the feature is completely implemented. This issue is becoming a show stopper.

kakone commented 7 years ago

I'm really curious to know the reasons to consider class table inheritance (or TPT) like an antipattern. You can use TPH, TPC or TPT, each one of them has its pros and cons. I think these three basic inheritance mapping strategies should be implemented. If you want to use an ORM on an existing database that uses TPT, it's difficult to choose EF Core because of this lack.

imuni4fun commented 7 years ago

I do hope this gets some attention soon. TPT really is a critical requirement when consistency is more important than raw throughput. There are often parts of an application that need throughput and should be optimized for that use case... at the same time, other parts can be fairly slow by comparison but it's critical that they be really concise and accurate and worth the wait. Tracking various types of transactions can be one example. It's more important that it's right than it's fast... as opposed to total 'likes', search results, etc. TPH can be sloppy by comparison as it prevents the specification of constraints possible with TPT.

JanEggers commented 7 years ago

im thinking of building tpt myself as this doesnt get any love for years. currently im using ef 6 and cant migrate because this feature is missing. problem is i dont really know what it takes to make it work. i guess i have to build some EntityTypeBuilder extensions to generate the correct metadata, but besides of that i could not find any code that needs to be touched but i guess the query visitors must be modified too but its just guessing....

fernandojs commented 6 years ago

Unfortunately, without TPT support the EF7 is stopping the upgrade for lot of apps in the .netCore world.

jimmymain commented 6 years ago

On Fri, 28 Jul 2017 at 4:09 PM fernandojs notifications@github.com wrote:

Unfortunately, without TPT support the EF7 is stopping the upgrade of lot of apps in the .netCore world.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/aspnet/EntityFramework/issues/2266#issuecomment-318661832, or mute the thread https://github.com/notifications/unsubscribe-auth/ACb8qtl9cFDadOSJYFrMJdWHD7hOaX1Tks5sSeuwgaJpZM4EnOQ5 .

Yes it is - come on guys - give us a roadmap. EF6 with its few frustrations really rocks compared to the competition. Particularly for the .Include method.

Give us some guidance.

gravbox commented 6 years ago

I am trying to move the nHydrate modeler forward to EF Core and the main stumbling block is no TPT. I need this to make the EF Core generation compatible with the EF6 implementation. This seems so simple, why can you not just join the tables in the hierarchy on the PK and be done with it? How is a database join an anti-pattern?

ghost commented 6 years ago

Guess this isn't ready for production use yet. I'm not going to rip apart my existing database (despite its design flaws) to accommodate the lack of EF Core features. Maybe when 3.0 comes around it'll be useful. Too bad, because .NET Core adoption is important to us, but not to the point of constantly working around missing features.

marchy commented 6 years ago

EF Core is far from being ready for real production use. Best advice: stay the heck away from it and keep using EF6. Your business will thank you for it.

PS: This also means you cannot use .NET Core and must use .NET Framework – which means you cannot dev on MacOS for anything other than research/hobby projects. The chain of dependencies is still bottlenecked :(

ghost commented 6 years ago

Not using .NET Core is not really an option when developing microservices that have a small footprint. The full .NET stack is too large to create a reasonably-sized container.

I've had some success by mapping an entity model to a domain model. This seems to be the direction that many people are going, and there's a lot to recommend this approach. It is, however, more work. In general, though, it's not going to be possible to force a good DDD model into an ORM. EF Core just makes this fact a little more obvious...

marchy commented 6 years ago

@cubikca Great point on the microservices part. Another way to put this is that microservice arch on .NET is not yet feasible in practice/production systems.

What do you mean by mapping entity model to domain model though? Do you mean having two separate model layers? If this is the case it's directly against the EF code-first goals/spirit (ie: to squish your Data Access layer and Modelling layer into one so that you don't have to maintain two layers and mapping between them) – which is quite a large architectural complexity/cost increase. I think it is entirely the EF's team goal to prevent the need for these kinds of approaches – which at least in the EF6 world they had achieved.

rorymurphy commented 6 years ago

It's disappointing to see that TPT and TPC are still not being prioritized and, given how long the issue has been open, it's tough to tell if it's actually coming or doomed to sit in purgatory forever.

Several good arguments for TPT & TPC have already been made but I'll throw in even another - TPH prevents you from being able to extend a DbContext in another assembly and add a child class of one of the entities (since there could be multiple assemblies doing this same thing, none of which can know about all the columns). It's not the microservices way of doing things, but can be useful, particularly if you don't control the code for the other assembly.

I won't argue that one is better than another, but each has its uses, and the opinionated stance that TPT and TPC are "nice to haves" and not really necessary is hurting adoption without a doubt.

jimmymain commented 6 years ago

What's completely nuts is that I discovered that server side group by wasn't even implemented until recently.

Imagine discovering all your grouping was being done "client" side a couple of weeks into a project.

Sorry - but EF Core is nothing more than a POC toy. It's not production ready at all.

On Sat, 26 Aug 2017 at 7:33 AM rorymurphy notifications@github.com wrote:

It's disappointing to see that TPT and TPC are still not being prioritized and, given how long the issue has been open, it's tough to tell if it's actually coming or doomed to sit in purgatory forever.

Several good arguments for TPT & TPC have already been made but I'll throw in even another - TPH prevents you from being able to extend a DbContext in another assembly and add a child class of one of the entities (since there could be multiple assemblies doing this same thing, none of which can know about all the columns). It's not the microservices way of doing things, but can be useful, particularly if you don't control the code for the other assembly.

I won't argue that one is better than another, but each has its uses, and the opinionated stance that TPT and TPC are "nice to haves" and not really necessary will hurt adoption without a doubt.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/aspnet/EntityFrameworkCore/issues/2266#issuecomment-325089259, or mute the thread https://github.com/notifications/unsubscribe-auth/ACb8qmnHm-zNwGRXLlwgCTk-lmr2e8SEks5sb64vgaJpZM4EnOQ5 .

simon-tamman commented 6 years ago

Remember that in many cases we don't get to choose our schema so this is a sticking point for transition. God knows what I'm going to have to do now seeing as we haven't got it. Some sort of gash composition shenanigans I guess. Ugh, my model is gonna look ugly as sin which then means I have to work harder at serialisation too because the default is going to be inefficient and wrong.
All of this is painful so it would be good if it wasn't.

ajcvickers commented 6 years ago

EF Team Triage: We really appreciate the recent feedback on this issue. Feedback from developers is extremely important in determining how resources across the team are assigned. However, please keep in mind that that feedback is only one of several inputs into the planning process and that--like in all software projects--resources are limited and every decision to implement a specific feature usually involves postponing others.

To shed a little more light onto our planning process we have created some documentation on the common considerations we take when deciding what to work on next.

We read and consider all feedback (and try to make the right choices based on it) no matter how it is delivered; that is, whether it is provided politely and with respect or not. Yelling at us at best makes you feel good and us feel bad. It doesn’t achieve anything concrete. We are doing our best to prioritize features and implement them in the best way we can. We really appreciate your feedback and it makes a big difference on shaping the product. We personally appreciate it more when feedback is delivered in a respectful way, but please don’t stop providing the feedback.

AndriySvyryd commented 6 years ago

The implementation could be simplified if we used a database model #8258

wcc-neal commented 6 years ago

Wait, this is still not available in EF core 2 ? Consider this another vote - pretty much required for our use case.

jaysanati commented 6 years ago

I just found the need to TPT and ended up to this discussion. I'm telling myself: "Welcome to the world of open source". We should learn to be patient.

JauernigIT commented 6 years ago

I just stumbled across this thread while searching for TPT in EF Core. Thanks to official Microsoft documentation, it's not obvious which types of inheritance are currently supported...

Now I found out here that TPT is not supported in EF Core, even not in v2.0. ARE YOU SERIOUS?! In my eyes, it's a crucial and base ORM feature. To still not have it is ridiculous (sorry to say this).

sthiakos commented 6 years ago

+1 For Me - Note to all that you should "thumbs up" the initial post by @satyajit-behera to vote up this issue. This and TPC is how DB's are/should be modeled.

sinjens commented 6 years ago

Also came here from Google searching for TPC/TPH inheritance model. In my last business system working for another company I had to make my own ORM due to TPT and performance, I really thought I wouldn't have to do that again. I'm with another company now, so I can't copy my old ORM either. EFCore seems very nice and to the point and I was in the middle of modeling and writing controllers when I suddenly realized that the only inheritance implementation is TPH :( That breaks my entire model. I'll have to look for another ORM now :(

crozone commented 6 years ago

I understand the need for this feature, but is writing an ORM really easier than working around it for now? Currently you can fake TPT by using composition, the current TPH, and non-mapped properties. Is it really such a big deal to either jump through a navigation property, or write boilerplate to do it for you?

rorymurphy commented 6 years ago

I'd say yes, it's a big deal to have to muck up the entire object model of your application to fit within the limitations of the ORM. Composition does not address all the same issues as inheritance - it's often not an option to swap one for the other.

gravbox commented 6 years ago

When you have a multi-million dollar project in the field that you cannot just re-write, it is kinda big deal that we cannot move to the next EF version. We have prepped everything for EFCore but we cannot move forward until this is addressed.

e-davidson commented 6 years ago

One of the benefits of EF core being open source is that you guys are free to implement it yourselves. Just my 2 cents.

fernandojs commented 6 years ago

@e-davidson Yes, it's. But, this feature is so complex, otherwise it would has been developed. Then if you couldn't help people here, please, don't waste your time. Your answer doesn't worth 2 cents.

gravbox commented 6 years ago

I guess I could rebuild my own car engine and re-roof my house too but why? Our business is building business solutions not ORM tools. We are not going to assign a developer to half-ass implement a custom solution that we then have to fully own and maintain forever. One depends on third party vendors to build the tools on which others then build more abstract software.

marchy commented 6 years ago

@fernandojs Agreed. Let's keep it constructive on here guys. We are all trying to steer the framework in the right direction and get the EF team the feedback they need to make the right priority calls. Currently this is a feature only THEY can execute and is blocking many of us from considering EFCore as a real alternative to EF 6.

Until then... let's hope that EF 6.3 can bring EF 6 to .NET Core so that we can at least have a migration path forward for our apps that are currently stuck on the full, heavy-weight .NET Framework (Issue here: https://github.com/aspnet/EntityFramework6/issues/271).

jeffreypalermo commented 6 years ago

At this point, the most complex applications I've built have used NHibernate. I look forward to when these can be converted to EF Core by updating the framework to 4.7.1 But there is a level of feature parity that has to ben achieved. What mappings should be included is a conversation that happened over the past 15 years. I believe those conversations have passed, and the industry has a body of knowledge built up through real usage of other ORMs. I believe EF Core should leverage this industry body of knowledge. http://nhibernate.info/doc/nhibernate-reference/inheritance.html#inheritance-strategies

SchneMa commented 6 years ago

Does anyone know a good workaround to use existing Databases with tpt inheritance?

weitzhandler commented 6 years ago

@SchneMa Entity Framework 6 😢

ajcvickers commented 6 years ago

Note: see also #10739

milosloub commented 6 years ago

Hello EF Core masters. Is there any progress in TPT or TPC? I'm developing enterprise financial system and several APIs are connected to IdentityServer. Each API has own type of user and each type is manipulated as complex hierarchy tree and joined to other related database tables. I can´t imagine to implement TPH only, because there are hundreds of thousands rows. Each user type has unique column structure ( from 10 - 40 unique columns against ancestor), so at this moment the result table is one big table with a lot of redundand optional empty rows ( most records comes from table with 10 unique columns).

Is there some hope that this is being implemented? Thank you

crozone commented 6 years ago

@milosloub It's on the backlog of high priority features, but won't make 2.1:

https://github.com/aspnet/EntityFrameworkCore/wiki/roadmap

However, TPH might not be as bad as you think. The cost of TPH can be reduced to a single byte for the discriminator row (by using a byte backed enum), and then a single bit for each null-able column that isn't used. You're looking at ~6 bytes overhead per row, maybe 9 depending on the database and padding.

jgonte commented 6 years ago

Any news on support for TPT?

Taken from: https://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt

TPT Advantages The primary advantage of this strategy is that the SQL schema is normalized. In addition, schema evolution is straightforward (modifying the base class or adding a new subclass is just a matter of modify/add one table). Integrity constraint definition are also straightforward (note how CardType in CreditCards table is now a non-nullable column).

brianjlowry commented 6 years ago

Additionally, in terms of creating indexing, indexes work better when you include all columns of the table to prevent column lookup. Not implementing this properly prevents one of the most important performance enhancements for a database (index seek vs. scan) - beyond the idea of having 50-100 columns for a model that only needs 10.