New Posts New Posts RSS Feed: Soft deletes and LINQ
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Soft deletes and LINQ

 Post Reply Post Reply
Author
mikedfox View Drop Down
Newbie
Newbie


Joined: 29-Apr-2010
Posts: 21
Post Options Post Options   Quote mikedfox Quote  Post ReplyReply Direct Link To This Post Topic: Soft deletes and LINQ
    Posted: 06-Dec-2010 at 11:04am
This isn't a problem specific to DevForce, but I'm hoping DevForce provides a better answer than EF.
 
I have a database where we are doing "soft deletes". So instead of a row being deleted, and IsDeleted flag is set to true. That way foreign key lookups still work, reporting on historical data still works, etc.
 
The problem comes when I try to look up related data, especially binding.
 
For example, let's say I have a book table and an author table. If hava reference to an author, I can bind to BookList.Count and see how many books are out there. Butr if one of the entries was a mistake, and has been marked as IsDeleted, how do I get the count straight? I know I can do another linq query, but can anyone figure out a better way? Would it be better to add properties on each partial class (ie UndeletedBooks on Author? Is there something EnttyListManager could add?
 
I know how to btrute force this, I'm jsut hoping there's a more elegant solution.
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 667
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 06-Dec-2010 at 12:36pm
Hi mikedfox;

I did a google search on Soft Delete. I would say the top 3 results are worth reading depending on your application's requirement. 

But I would say read this site first since it explores the reasons why we do soft deletes. It also attempts to provide a more elegant solution for each reason.

Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 667
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 06-Dec-2010 at 12:47pm
After reading this article:


I think it makes more sense if you add another state to your Book object that marks it as a "mistake" and you can do a count query that excludes for this "mistake" state.
Back to Top
mikedfox View Drop Down
Newbie
Newbie


Joined: 29-Apr-2010
Posts: 21
Post Options Post Options   Quote mikedfox Quote  Post ReplyReply Direct Link To This Post Posted: 06-Dec-2010 at 1:18pm
I don't have control over the data model.
Back to Top
mikedfox View Drop Down
Newbie
Newbie


Joined: 29-Apr-2010
Posts: 21
Post Options Post Options   Quote mikedfox Quote  Post ReplyReply Direct Link To This Post Posted: 07-Dec-2010 at 7:59am
I found an answer -
EntityServerQueryInterceptor
Back to Top
smi-mark View Drop Down
DevForce MVP
DevForce MVP
Avatar

Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 307
Post Options Post Options   Quote smi-mark Quote  Post ReplyReply Direct Link To This Post Posted: 07-Dec-2010 at 3:55pm
Yes, you've got it. Using the EntityServerQueryInterceptor, you can force it to always add a Where IsDeleted == false, so no matter what query you execute, it will only return entities that satisfy this condition.
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 667
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 08-Dec-2010 at 12:56pm
Great. Thank you for sharing your solution guys.
Back to Top
DenisK View Drop Down
IdeaBlade
IdeaBlade


Joined: 25-Aug-2010
Posts: 667
Post Options Post Options   Quote DenisK Quote  Post ReplyReply Direct Link To This Post Posted: 15-Dec-2010 at 5:50pm
For those who are interested, here is an alternative solution suggested by Ward Bell.

I prefer either of the following:

  • 1.      Two properties: one for all and one for active books
  • 2.      A property that returns only active books; a method (“GetAllBooks()”) that returns everything. 

#2 is cleanest but you can’t bind to a method … which is why I usually end up with #1.  

Think about what Author.Books should return in the usual case.  Should it (a) return all books or (b) return active books. 

DevForce by default generates a “Books” property for the (a) interpretation.  Most people want the “Books” property to behave like (b). Therefore, I would: 

  1. ·        Rename (in the EDM) the “Books” navigation property to “AllBooks” (or some such convention)
  2. ·        Add a custom “Books” property to the Author partial class that returns only active books. 

One possible implementation of that custom property is: 

 public partial class // extends the generated Author class
 {
     /// <summary>Gets the Author’s active Books (books that are not deleted).</summary>
     [Bindable(false)]
     [Display(Name = "Books", AutoGenerateField = false)]
     public RelatedEntityList<Book> Books
     {
         get { return new RelatedEntityList<Book>(
                  this.Books.Where(b=>b.Active == true),
                  PropertyMetadata.Books.GetEntityReference(this)
                  ); }
     }
 }

 

It is no accident that this looks very similar to the code that DevForce generated for Author.AllBooks. 

It is not the only possible implementation. RelatedEntityList<Tis a DevForce internal class … one that, in general, you should not create yourself. The advantage is that this is a “live” list; if you toggle a Book between active and deleted, this list updates automatically (adding or removing a Book automatically). 

Please remember that sub-queries and INCLUDEs must be composed in terms of the AllBooks property.  Neither EF nor DevForce will recognize the Books property.
Back to Top
mikedfox View Drop Down
Newbie
Newbie


Joined: 29-Apr-2010
Posts: 21
Post Options Post Options   Quote mikedfox Quote  Post ReplyReply Direct Link To This Post Posted: 12-Jan-2011 at 6:39am
thanks Dennis, I figured out why Ward is suggesting that - the queryinterceptor filter doesn't get applied to navigation properties.
 
So if Author has Books, and I use the queryinterceptor filter method, querying books will not return the soft deleted rows, but accessing the Author.Books collection will.
 
I thought I remembered the old pre-ef DevForce giving you a way to add a filter clause to a relationship. Wish that was still there. Guess I'll go with a) above, but that is a lot of relationships to go update :(
 
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down