I have found some information regarding this but not enough for me to understand what the best practice for is for this scenario. I have your typicaly TPH setup with an abs
EDIT: APOLOGIES, THIS IS AN EF 6.x ANSWER
I'm posting example code for completeness. In this scenario, I have a base Thing class. Then, sub-classes: ActiveThing and DeletedThing
My OData ThingsController, has a main GetThings which I intend to only expose ActiveThings, but, it's GetThing(ThingId) can still return either type of object. The Delete action performs a conversion from ActiveThing to DeletedThing much in the way requested by the OP, and much in the manner described in other answers. I'm using inline SQL (parameterized)
public class myDbModel:DbContext
{
public myDbModel(): base("name=ThingDb"){}
public DbSet Things { get; set; } //db table
public DbSet ActiveThings { get; set; } // now my ThingsController 'GetThings' pulls from this
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//TPH (table-per-hierarchy):
modelBuilder.Entity()
.Map(thg => thg.Requires("Discriminator").HasValue("A"))
.Map(thg => thg.Requires("Discriminator").HasValue("D"));
}
}
Here's my updated ThingsController.cs
public class ThingsController : ODataController
{
private myDbModel db = new myDbModel();
///
/// Only exposes ActiveThings (not DeletedThings)
///
///
[EnableQuery]
public IQueryable GetThings()
{
return db.ActiveThings;
}
public async Task Delete([FromODataUri] long key)
{
using (var context = new myDbModel())
{
using (var transaction = context.Database.BeginTransaction())
{
Thing thing = await db.Things.FindAsync(key);
if (thing == null || thing is DeletedThing) // love the simple expressiveness here
{
return NotFound();//was already deleted previously, so return NotFound status code
}
//soft delete: converts ActiveThing to DeletedThing via direct query to DB
context.Database.ExecuteSqlCommand(
"UPDATE Things SET Discriminator='D', DeletedOn=@NowDate WHERE Id=@ThingId",
new SqlParameter("@ThingId", key),
new SqlParameter("@NowDate", DateTimeOffset.Now)
);
context.ThingTransactionHistory.Add(new Ross.Biz.ThingStatusLocation.ThingTransactionHistory
{
ThingId = thing.Id,
TransactionTime = DateTimeOffset.Now,
TransactionCode = "DEL",
UpdateUser = User.Identity.Name,
UpdateValue = "MARKED DELETED"
});
context.SaveChanges();
transaction.Commit();
}
}
return StatusCode(HttpStatusCode.NoContent);
}
}