Как создать DbModificationClause с помощью CASE WHEN .... THEN
Все
Я был создан IDbCommandTreeInterceptor и получил проблему: EF провайдер неправильно генерации SQL. В результате я хочу получить этот SQL
UPDATE [dbo].[Devices] SET [DeletedDate] = CASE
WHEN [DeletedDate] IS NULL THEN GETUTCDATE()
ELSE [DeletedDate] END
Код для тестирования. Класс Interseptor для поддельного удаления.
public class SoftDeleteInterseptor : IDbCommandTreeInterceptor
{
private const string DELETED_DATE_COLUMN = "DeletedDate";
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
{
if (interceptionContext.OriginalResult.DataSpace != DataSpace.SSpace)
{
return;
}
var deleteCommand = interceptionContext.OriginalResult as DbDeleteCommandTree;
if (deleteCommand != null)
{
interceptionContext.Result = HandleDeleteCommand(deleteCommand);
return;
}
}
private DbCommandTree HandleDeleteCommand(DbDeleteCommandTree deleteCommand)
{
if (!IsPropertyExists(deleteCommand, DELETED_DATE_COLUMN))
{
return deleteCommand;
}
var deletedProperty = DbExpressionBuilder.Property(
DbExpressionBuilder.Variable(deleteCommand.Target.VariableType, deleteCommand.Target.VariableName),
DELETED_DATE_COLUMN
);
var caseValue = DbExpressionBuilder.Case(
new DbExpression[] { deletedProperty.IsNull() },
new DbExpression[] { EdmFunctions.CurrentUtcDateTime() },
deletedProperty);
var setClauses = new List<DbModificationClause> { DbExpressionBuilder.SetClause(deletedProperty, caseValue) };
return new DbUpdateCommandTree(
deleteCommand.MetadataWorkspace,
deleteCommand.DataSpace,
deleteCommand.Target,
deleteCommand.Predicate,
setClauses.AsReadOnly(), null);
}
private bool IsPropertyExists(DbModificationCommandTree command, string property)
{
var table = (EntityType)command.Target.VariableType.EdmType;
return table.Properties.Any(p => p.Name == property);
}
}
Создать класс конфигурации для регистра DbInterseptor.
public class CustomDbConfiguration : DbConfiguration
{
public CustomDbConfiguration()
{
AddInterceptor(new SoftDeleteInterseptor());
}
}
public partial class CustomDbContext : DbContext
{
static IDCompleteDbContext()
{
DbConfiguration.SetConfiguration(new CustomDbConfiguration());
}
public virtual DbSet<CommandEntity> CommandEntities { get; set; }
}
public class CommandEntity
{
public int Id {get; set;}
public DateTime? DeletedDate {get; set;}
public string Name {get; set;}
}
При удалении сущности, сущность не удалялась
var context = new CustomDbContext();
var entity = context.CommandEntities.First();
context.CommandEntities.Remove(entity);
context.SubmitChanges();
Не работал. EF-провайдер генерирует неправильный SQL: UPDATE [dbo].[Устройства] SET [DeletedDate] = [DeletedDate] IS NULL@0[DeletedDate] WHERE ([Id] = @1) @0: '01.05.2018 7:45:22' (Type = DateTime2) @1: '20' (Type = Int32)