Alex (Xtensive) wrote:
I think it's a bad idea: soft removes normally don't imply any reference cleanup; business rules there can be quite different.
IMHO, the best approach is to add your own SoftRemove method (possibly - extension method) with all the infrastructure you need for this (e.g. your own event-like methods), and use our own Remove() method only for "hard" removes.
stefmen wrote:
Hi Paul,
We also want soft removes in our application.
All our entities inherit from this class:
public abstract class DefaultEntity<T> : Entity where T : DefaultEntity<T>, new()
{
/// <summary>
/// The identifier of the entity.
/// </summary>
[Key, Field]
public Int32 Id { get; private set; }
/// <summary>
/// Created by user.
/// </summary>
[Field(Nullable = true)]
[Association()]
public ApplicationUser CreatedBy { get; set; }
/// <summary>
/// Created on date.
/// </summary>
[Field(Nullable = false)]
public DateTime Created { get; set; }
/// <summary>
/// Last modified by user.
/// </summary>
[Field(Nullable = true)]
[Association()]
public ApplicationUser ModifiedBy { get; set; }
/// <summary>
/// Last modified on date.
/// </summary>
[Field(Nullable = true)]
public DateTime? Modified { get; set; }
//To Paul: When you do this you allways have these fields with your entities.
[b] /// <summary>
/// Deleted by user.
/// </summary>
[Field(Nullable = true)]
[Association()]
public ApplicationUser DeletedBy { get; set; }
/// <summary>
/// Deleted on date (if not null).
/// </summary>
[Field(Nullable = true)]
public DateTime? Deleted { get; set; }[/b]
/// <summary>
/// Logicaldelete of the current entity.
/// </summary>
public new void Remove()
{
this.Deleted = DateTime.Now;
this.DeletedBy = DomainInfo.CurrentUser;
}
/// <summary>
/// Deletes the current entity
/// </summary>
/// <param name="RemovePermanently">True if you want to delete the record permanently!</param>
public void Remove(bool RemovePermanently)
{
if (RemovePermanently)
{
base.Remove();
}
else
{
this.Remove();
}
}
It's easy to specify this method so that deleted values are automatically excluded:
/// <summary>
/// Gets all the (not deleted) entities of this type.
/// </summary>
/// <returns>IQueryable resultlist</returns>
public static IQueryable<T> GetAll()
{
return Query.All<T>().Where(p => p.Deleted == null);
}
The class that you want to create looks like this:
[Serializable]
[HierarchyRoot(InheritanceSchema = InheritanceSchema.SingleTable)]
public class AppointmentCore : DefaultEntity<AppointmentCore>
{
//All your classspecific properties go here
//All the properties and methods specified in the DefaultEntity class are accessible here.
}
I also agree with Alex; reference cleanup isn't performed, so you should be aware of this.
Alex (Xtensive) wrote:
It seems you're trying to implement operation logging + undo for removals - the original entity gets deleted anyway, so this isn't what normally called "soft removal".
If you really need this feature (undo + operation logging), may be it's a good idea to acquire a license and push with this on us ;) Actually, it's one of long promised features; a lot of work necessary to implement it is already done - there is Operations framework used by DisconnectedState, that already implements "do" part; + we tested our approach for "undo" in Integrity.Atomicity, although we already decided to use much simpler approach in Xtensive.Storage.
So in short, I think there are two good ways:
-
Implement soft removals w/o significant integration with DO4.
-
Push on us with operation logging & undo/redo. This will require some time (may be few months), but when it's done, it will work everywhere, i.e. not just for removal. And in this case you won't need to implement anything except UI part for this.
Alex (Xtensive) wrote:
Btw, about the approach: being on your place, I'd seriously think about adding ISupportsSoftRemove interface + few extension methods to it, as well as some service allowing to e.g. find all of such objects and actually delete them.
Alex (Xtensive) wrote:
Clear. I'd also prefer operation logging instead of soft deletes, if purpose is just logging & possibility to do a kind of rollback - at least to keep the working set (and indexes) smaller.
You're right about undo and upgrade. We'll think about providing custom serializer + operation processor to handle this case.
answered
Jun 22 '10 at 07:31
Editor
46●156●156●157