I am trying to remove child item(s) from my domain, but Savechanges() is not working and no exceptions occurred and I am tracing and find my entity in Dbcontext that state changed to modified. add or update working correctly. everything worked ok before I add IEventbus interface to publish an event. my remove method in the domain class.
public void RemoveItem(Guid id, IEventBus eventBus)
{
if (!string.IsNullOrWhiteSpace(this.Confirmer.UserId))
{
throw new RemoveItemOfConfirmedScrapException();
}
var scrapItem = this.ScrapItems.First(p => p.Id == id);
var assetId = scrapItem.AssetId;
this.ScrapItems.Remove(this.ScrapItems.First(p => p.Id == id));
eventBus.Publish(new ScrapItemRemovedEvent(assetId));
}
and this is my UnitOfWork for saving in the database.
public class UnitOfWork : IUnitWork
{
private readonly IDbContext dbContext;
private DbContextBase dbContextBase;
public UnitOfWork(IDbContext dbContext)
{
this.dbContext = dbContext;
this.dbContextBase = dbContext as DbContextBase;
}
public void Commit()
{
try
{
this.dbContext.SaveChanges();
}
catch
{
RollBack();
throw;
}
}
public void RollBack()
{
this.dbContextBase.ChangeTracker.Entries()
.Where(e => e.Entity != null).ToList()
.ForEach(e => e.State = EntityState.Detached);
}
}
what happens to that delete works in other domains even in parent entity but in this case not delete in database. and ChangeTracker shows that specific entity state changed to "modified" but without any exception finish job and not effected on the database.
I have an application service layer with decoration design pattern to call UnitOfWork
public void Dispatch<TCommand>(TCommand command)
where TCommand : Command
{
var commandHandler = this.diContainer.Resolve<ICommandHandler<TCommand>>();
var transactionCommandHandler = new TransactionalCommandHandler<TCommand>(commandHandler, this.diContainer);
var logCommandHandler = new LogCommandHandler<TCommand>(transactionCommandHandler);
logCommandHandler.Execute(command);
}
and transactional class that calls UnitOfWork
public class TransactionalCommandHandler<TCommand> : ICommandHandler<TCommand>
where TCommand : Command
{
private readonly ICommandHandler<TCommand> commandHandler;
private readonly IDiContainer container;
public TransactionalCommandHandler(ICommandHandler<TCommand> commandHandler, IDiContainer container)
{
this.commandHandler = commandHandler;
this.container = container;
}
public void Execute(TCommand command)
{
var unitOfWork = this.container.Resolve<IUnitWork>(); // ServiceLocator.Current.Resolve<IUnitWork>();
try
{
this.commandHandler.Execute(command);
unitOfWork.Commit();
}
catch (Exception e)
{
unitOfWork.RollBack();
throw;
}
}
}
A very simple carelessness had caused this problem. in my command facade have transaction scope that forgot put "scope.complete()"
public void DeleteScrapItem(DeleteScrapItemCommand command)
{
using (var scope = new TransactionScope())
{
Action<dynamic> updateAssetStatus = p => this.CommandBus.Dispatch(new UpdateAssetStatusCommand()
{
AssetId = p.AssetId,
Status = 0
});
this.eventBus.Subscribe<ScrapItemRemovedEvent>(updateAssetStatus);
this.CommandBus.Dispatch(command);
scope.Complete(); // forgot put this ...
}
}