Тёмный

The Best Way To Implement Soft Deletes With EF Core (and why you shouldn't) 

Milan Jovanović
Подписаться 106 тыс.
Просмотров 14 тыс.
50% 1

Опубликовано:

 

27 окт 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 76   
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Want to master Clean Architecture? Go here: bit.ly/3PupkOJ Want to unlock Modular Monoliths? Go here: bit.ly/3SXlzSt
@silverfox3074
@silverfox3074 3 месяца назад
Excellent video! But I was thinking if there is any way that filter by isDeleted to be automatically? For example not to check every record if isDeleted but method where to handle this automatically?
@Isr5d
@Isr5d 4 месяца назад
Soft delete is a great feature if you want to add 2-step deletion process to the user. User can recover the deleted items within a respected period of time, or can delete them permanently. In case the time of deletion has reached the recovery time threshold, the system will delete them permanently. It's like user recycle bin. You can adapt hierarchy approval to it as well. So user will soft delete the entry, but a supervisor can either approve deletion process or reject it.
@ajdinhusic2574
@ajdinhusic2574 4 месяца назад
There is additional reasons to use soft deletes. Sometimes you need to retain related data, like calculations, results, statistics, reports etc.. Often times you dont want to destroy those just because a record was deleted
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
That's a very nice use case
@Kingside88
@Kingside88 4 месяца назад
Thank you, Milan. An incredibly good explanation.
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Glad you enjoyed it!
@PurpleDaemon_
@PurpleDaemon_ 4 месяца назад
10:12 a filtered index on a bool fields one only makes sense in the opposite case, when you are filtering a much smaller part. In your case, your index will cut off a couple of percent at most and will most likely be completely ignored by the base. And here are two additional things to think about when implementing a soft-delete: 1) Without additional changes hidden objects will still be taken into account when checking the uniqueness of fields by the database 2) Soft-deliting an object with cascading dependencies can lead to an invalid state of the database.
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
1) That's a nice problem to consider. But I'd look at it as a business decision and see what makes sense. Maybe we can make due without a unique check, and do a query at runtime. 2) How so? As in, the dependents wouldn't be marked as deleted?
@PurpleDaemon_
@PurpleDaemon_ 4 месяца назад
@@MilanJovanovicTech 2 - yep, you could have items with soft-deleted parent, which can easily break FE or other stuff.
@saleem.shaikh
@saleem.shaikh 4 месяца назад
Next video, if you can, please do a video on audit trail, and how to implement it, can we use mediatr for it or not.
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
I discussed how to do this with EF Core: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-mAlO3OuoQvo.html
@user-kh8mv2be8t
@user-kh8mv2be8t 3 месяца назад
It is better to do this kind of thing using the SavingChanges delegate rather than overriding the SaveChangesAsync. There are multiple SaveChangesAsync overloads which internally call SaveChangesAsync(bool, CancellationToken), so you'd need to make sure you are overriding the correct one or else your logic will get skipped if a different signature is invoked, this also doesn't cover non-async calls using the SaveChanges() method, so you'd need to cover that set as well to implement this properly, finally the dispose check code runs just before that delegate is invoked, which will give you a nicer and more consistent error message if someone tried to invoke the method on a disposed instance. This also allows you to either include it in the class as you do here or attach the logic as needed.
@MilanJovanovicTech
@MilanJovanovicTech 3 месяца назад
I only ever call SaveChangesAsync from my code, but that's a valid concern. We could move this logic into an interceptor, though.
@kewqie
@kewqie 4 месяца назад
At 4:15, why not just do "product.IsDeleted = true;" before calling "Update(product)" instead of doing that long ".Property()" call after?
@ajdinhusic2574
@ajdinhusic2574 4 месяца назад
product.IsDeleted = true marks the EntityState as Updated, and so an Update Event is fired instead of a Delete event.
@kewqie
@kewqie 4 месяца назад
@@ajdinhusic2574 isn't that done by the Update()? He talks about it 15s earlier.
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
1) IsDeleted had a private set 2) Yeah, Update isn't necessary there. But just wanted to make it explicit since I had Remove() beforehand.
@kjbetz
@kjbetz 4 месяца назад
Excellent video as always Milan!
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Thanks a lot!
3 месяца назад
I think in terms of ddd and clean architecture it would be better to use a shadow property in the EF configuration instead of modifying the domain layer
@MilanJovanovicTech
@MilanJovanovicTech 3 месяца назад
That might make sense, yeah
@ajdinhusic2574
@ajdinhusic2574 4 месяца назад
I feel like there must be a library by now for soft-deletes using EF core, right? Also Milan, what do you say about implementing ISoftDeletable using a nullable DateTime(Offset) type for the deletion marking. as this contains more information that might be useful. The filter and index would then be on: DeletedAt == null .
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
I believe I mentioned that we could use a DateTime column 🤔 Fine by me.
@ajdinhusic2574
@ajdinhusic2574 4 месяца назад
@@MilanJovanovicTech yeah but I thought you meant as an additional column alongside the boolean? Or instead of the boolean? If its instead of the boolean then yes thats what I meant. Which do you prefer btw?
@andyhb1970
@andyhb1970 4 месяца назад
I find soft deletes to be invaluable, firstly it enables easier tracking of deletes for migrating changes via ETL processes to external systems and secondly users can't be trusted and soft deletes have saved many a painful situation over the years 🎉
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Let's go soft deletes! 😁
@daniel_klement_photography
@daniel_klement_photography 3 месяца назад
More this simple and useful videos!
@MilanJovanovicTech
@MilanJovanovicTech 3 месяца назад
Will do :)
@arteqppp6223
@arteqppp6223 3 месяца назад
Any reason not to do some base AuditableEntity class, which would have IsDeleted, DeletedOnUtc, Id, itd for all of entites?
@MilanJovanovicTech
@MilanJovanovicTech 3 месяца назад
I'm just giving ideas here, you can take it further with something like that 😁
@arteqppp6223
@arteqppp6223 3 месяца назад
@@MilanJovanovicTech Sure, thanks!
@saleem.shaikh
@saleem.shaikh 4 месяца назад
Nice video.
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Thanks a llot!
@ChrisWard74
@ChrisWard74 4 месяца назад
I'm new to EF Core so I have lots to learn. When you added IsDeleted you had a Migrate function do you have more details on what that is/does? Do you write that function and it's run one time to modify the database?
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
It's an extension method that applies EF Core migrations when the application starts. dbContext.Database.Migrate();
@ChrisWard74
@ChrisWard74 4 месяца назад
@@MilanJovanovicTech Wouldn't it be better to do these migrations outside of code in a SQL script? Over time you could have more and more migrations as things change so you wouldn't want all of those migrations running every time or checking to see if they need to run every time the application is started.
@yotelolailo
@yotelolailo 2 месяца назад
@@ChrisWard74 They are run only in development environments. Usually for production environments you have to select a different technique to run your migrations manually or automated but not on every application start.
@AlejandroPerez-m9r
@AlejandroPerez-m9r 4 месяца назад
Could you please tell me which visual theme you use, or could you share the colors you use in your configuration, or make a video about it? Thank you very much.
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
ReSharper
@AlejandroPerez-m9r
@AlejandroPerez-m9r 4 месяца назад
@@MilanJovanovicTech Would you be so kind as to indicate how to achieve that configuration, please?
@romualdhenry1633
@romualdhenry1633 4 месяца назад
Hi Milan thank you for all of your videos ! I have a question about Clean Architecture, I would to do some Business Calculations (like calculate prices), and I would like to know in what layer I should do and in what class Thank you so much ❤
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Probably Application, but hard to tell without context
@ajdinhusic2574
@ajdinhusic2574 4 месяца назад
@@MilanJovanovicTech exactly. First that comes to mind is application, but like you said, it depends. For example, many calculations can often times be attributed to the domain layer. Its often worth to think about it more closely.
@matthewrossee
@matthewrossee 4 месяца назад
Hi Milan! How would you implement cross-cutting concerns like validation or caching WITHOUT using MediatR and its pipelines? Let's say the classical service architecture. Maybe one could use a decorator pattern with Scrutor. Do you know how to implement something like this?
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Middleware? 🤔
@matthewrossee
@matthewrossee 4 месяца назад
@@MilanJovanovicTech I guess it’s an option but seems a bit clunky. Can’t find a good repo that demonstrates something different than mediatr pipelines
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
@@matthewrossee Which is why MediatR is so awesome. I never understood the hate against, considering how many awesome options it unlocks.
@matthewrossee
@matthewrossee 4 месяца назад
@@MilanJovanovicTech have you used the Martin Othamar’s mediator implementation? The same API, but uses source generated code, maybe you’ll find this interesting.
@alexxx8338
@alexxx8338 4 месяца назад
Found problems imlementing this on my aggregate with nested soft delete entities collections in it. Quer filters are not going to solve my problems in this case
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
True. Collections make this quite a bit harder.
@haroldpepete
@haroldpepete 4 месяца назад
great video, i implemented sofdelete in one project, but some questions come to my mind, what happen if i mark a isdeleted flag in one record, a producct record for taking an example, when i try to register another product with the same name like my softdelete flag and my database has a unique constraint by name? how i can manage this behavior? because i gonna have problem trying to register a new product with the same name with some product marked as softdelete
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
That's a business question, not a technical one
@PurpleDaemon_
@PurpleDaemon_ 4 месяца назад
Depending on you DB use nullable bool field or filtered index.
@ibowyer
@ibowyer 4 месяца назад
I have used temporal tables in ef core for archiving data changes before do you think that is another possible solution?
@ajdinhusic2574
@ajdinhusic2574 4 месяца назад
Yes, that reminds me of that event sourcing pattern that was recently highlighted by Nick Chapsas
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Yes, albeit more complex
@هواتف-م9ر
@هواتف-م9ر 4 месяца назад
Thanks 👍
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Any time!
@saddamhossaindotnet
@saddamhossaindotnet 4 месяца назад
Excellent content!
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Much appreciated!
@barr5221
@barr5221 4 месяца назад
what about SQL server temporal table or table with from and until date? Soft deletes + full history of the changes on the table. Very usefull when debugging what happended to your data.
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
Too complex for this video 😅
@kman12275
@kman12275 4 месяца назад
I love the temporal tables most of the time. I am considering a soft delete though where the user might bring the record back.
@andyhb1970
@andyhb1970 4 месяца назад
SQL Change Data Capture works extremely well and I've used it to feed an ETL process to our data warehouse and it all works perfectly in Azure SQL as well.
@RikinPatel13
@RikinPatel13 4 месяца назад
How to do same things in CosmosDB with Linq?
@MilanJovanovicTech
@MilanJovanovicTech 4 месяца назад
No idea
@codenetw
@codenetw 4 месяца назад
How about not creating additional entities in the database and maintaining them by moving items, but instead simply partitioning by the IsDeleted flag? When querying with a filter, the database will more easily select from the partition where IsDeleted = false. create table if not exists products ( ... product text, isDeleted boolean ) PARTITION BY LIST (isDeleted); CREATE TABLE products_new PARTITION OF products FOR VALUES IN (false); CREATE TABLE products_deleted PARTITION OF products FOR VALUES IN (true);
@MilanJovanovicTech
@MilanJovanovicTech 3 месяца назад
I think that's a PostgreSQL feature, right? Would it automatically move records from the products_new to products_deleted partition on update?
@codenetw
@codenetw 3 месяца назад
@@MilanJovanovicTech I thought that mssql also supports this function, but yes, you are right, it will not allow you to update the record if it is a key for the partition :(
Далее
Are You Accidentally Crippling Your EF Core Queries?
17:18
Страшная Тайна Светы Кемер !
33:04
Бокс - Финты Дмитрия Бивола
00:31
The Alternative to Deleting Data in .NET
11:11
Просмотров 37 тыс.
Exceptions Are Extremely Expensive… Do This Instead
17:15
So You Want To Implement Soft Deletes In SQL Server
18:29
EF Core Multitenancy For Your SaaS Applications
14:41
Building better DTOs in C#
11:57
Просмотров 6 тыс.
Using EF Core’s Coolest Feature to Audit in .NET
26:06
Don’t Use UUIDs/GUIDs in Databases. Use this Instead
10:36
Full Text Search in .NET With PostgreSQL and EF Core
24:13
Don't Use Polly in .NET Directly. Use this instead!
14:58