Em um aplicativo .NET 6 C# com Entity Framework 7 (as mudanças para 8 e 8, respectivamente, estão chegando), temos várias tabelas com uma coluna chamada DateUpdated. Cada vez que uma linha é adicionada ou atualizada, esta coluna deve receber a data e hora atual. Esse é o tipo de coisa que pode ser tratada no lado do servidor de dados com um gatilho, mas existe um gancho em DbContext ou DbSet para permitir a inserção de uma funcionalidade como essa? Estou imaginando que as classes POCO para essas tabelas poderiam implementar ITrackable:
public interface ITrackable
{
DateTime DateUpdated { get; set; }
}
public class Employees : ITrackable
{
int EmployeeId { get; set; }
/* etc. */
DateTime DateUpdated { get; set; }
}
Então, para classes que implementam ITrackable, onde a classe de contexto do banco de dados normalmente teria
public DbSet<Employee> Employees => Set<Employee>();
DbContext.Set pode ser substituído ou uma classe pode ser derivada de DbSet ou algo assim, em algum lugar antes ou durante SaveChanges/SaveChangesAsync,
foreach (var item in [items being updated])
{
item.DateUpdated = DateTime.UtcNow;
}
é executado em cada linha adicionada ou atualizada antes que o Entity Framework envie os dados para o banco de dados.
Existe uma maneira integrada de fazer isso ou de adicionar esse recurso?
Pergunta bônus: se isso puder ser feito, diga que a situação é um pouco mais complexa - o valor a ser definido na coluna vem de um serviço que injetei no contexto:
private IMyService myService;
public AppContext(DbContextOptions<AppContext> options, IMyService myService)
: base(options)
{
_myService = myService;
}
Ainda pode ser feito?
Não é muito complicado de suportar. O método que uso onde algumas entidades podem ter esse comportamento, mas outras não, é ter uma interface expondo The DateUpdated que qualquer entidade de suporte implementa:
Essas tabelas devem ser configuradas como padrão para UTCNow na inserção ou, no pior caso, padronizadas na propriedade da classe de entidade.
Em seguida
DbContext
, substitua oOnSaveChanges
para destacar quaisquer entidades modificadas que estendam essa interface e injete o valor atualizado:Você também precisará de uma substituição
SaveChangesAsync
se utilizarasync
chamadas.Isso deve proporcionar o comportamento desejado, embora possa precisar de alguns ajustes à medida que o exemplo é extraído da memória, embora eu acredite que a expressão Linq deva funcionar. (Pode ser necessário um
Cast<IUpdateStamped>()
)