Weej
Weej

Reputation: 1022

Breeze Server Side: Change EntityState to enable soft deletes

I want to make soft-deletes in my database. I'd handle deletes to the database by flagging deletes by setting an IsDeleted value to true. Correspondingly, I want Breeze queries to exclude rows with the IsDeleted flag set.

I prefer to do this on the server-side rather than on the client.

I can intercept the delete in a custom Breeze EFContextProvider and set the IsDeleted attribute. I'd want to set entityInfo.EntityState = EntityState.Modified and continue with the update. However, it appears that the entityInfo.EntityState is read-only.

Is there some other way to accomplish this?

Upvotes: 1

Views: 745

Answers (4)

Mike Thibault
Mike Thibault

Reputation: 213

I think I may have found a good way of doing this server side with Entity Framework.

You'll need to create a stored procedure that sets IsDeleted to true for a particular row in your table.

Then in your edmx file, go to the Mapping Details for your entity, and select Map Entity to Functions. Click on and supply it your SP.

If you're using code first, maybe this can help do the same: https://msdn.microsoft.com/en-us/data/dn468673.aspx

Upvotes: 1

julianpaulozzi
julianpaulozzi

Reputation: 323

One current way it works, is not very elegant because it uses reflection, but better than not having solution.

Follows a very simplified way that I use with using 'ExclusionDate' property:

// Model  -----------------------------------

public interface ISoftDelete
{
    DateTime? ExclusionDate { get; set; } 
}

public class Order : ISoftDelete
{
    // Props...
    public DateTime? ExclusionDate { get; set; }
}

// ------------------------------------------

// Data -------------------------------------

public interface IBreezeRepository<out T>
{
    IQueryable<T> All();
}

public class SoftRepository<T> : 
    IBreezeRepository<T> where T : class, ISoftDelete
{
    public SoftRepository(DbContext context)
    {
        Context = context;
    }

    protected DbContext Context { get; private set; }

    public IQueryable<T> All()
    {
        return Context.Set<T>().Where(p=> !p.ExclusionDate.HasValue);
    }
}

public class UnitOfWork
{
    private readonly EFContextProvider<EcmContext> _contextProvider;

    public UnitOfWork()
    {
        _contextProvider = new EFContextProvider<EcmContext>
        {
            BeforeSaveEntityDelegate = BeforeSaveEntity
        };

        var context = _contextProvider.Context;
        Orders = new SoftRepository<Order>(context);
    }

    public IBreezeRepository<Order> Orders { get; private set; }

    private bool BeforeSaveEntity(EntityInfo entityInfo)
    {
        var entityType = entityInfo.Entity.GetType();
        // a little reflection magic
        if (typeof(ISoftDelete).IsAssignableFrom(entityType) && 
            entityInfo.EntityState == EntityState.Deleted)
        {
            entityInfo.GetType().GetProperty("EntityState")
                      .SetValue(entityInfo, EntityState.Modified, null);
            var entity = entityInfo.Entity as ISoftDelete;
            if (entity != null)
            {
                entity.ExclusionDate = DateTime.Now;
                entityInfo.ForceUpdate = true;
            }
        }

        return true;
    }
}

// -------------------------------------------

See: How to perform logical delete with Breeze JS?

Upvotes: 0

pawel
pawel

Reputation: 371

You can override BeforeSaveEntities(). Remove entries with EntityState.Deleted from the map and add them again with EntityState.Modified. You will need breeze v 1.3.3.

Upvotes: 0

Jay Traband
Jay Traband

Reputation: 17052

You can use the EntityAspect.setModified, setDeleted, and setUnchanged methods to accomplish this. i.e.

myEntity.entityAspect.setModified();

Upvotes: 0

Related Questions