我正在使用ASP.NET Core + Entity Framework 开发一个web应用程序。
我想存储更多关于创建,修改和删除的信息。
我的EF实体实现了接口,这些接口带来了以下字段:
DateTime CreationTime { get; set; }long? CreatorUserId { get; set; }DateTime? ModificationTime { get; set; }long? ModifierUserId { get; set; }DateTime? DeletionTime { get; set; }public long? DeleterUserId { get; set; }bool IsDeleted { get; set; }int TenantId { get; set; }我一直在努力使我的应用程序设置所有的字段automatically.
现在,我只能处理DateTime字段:
AppDbContext.cs
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
ChangeTracker.DetectChanges();
ChangeTracker.ProcessModifiedTime();
ChangeTracker.ProcessSoftDelete();
ChangeTracker.ProcessCreationTime();
return (await base.SaveChangesAsync(true, cancellationToken));
}ChangeTrackerExtensions.cs
public static class ChangeTrackerExtensions
{
public static void ProcessCreationTime(this ChangeTracker changeTracker)
{
foreach (var item in changeTracker.Entries<ICreationTime>().Where(e => e.State == EntityState.Added))
{
item.CurrentValues[AppConsts.CreationTime] = DateTime.Now;
}
}
public static void ProcessModifiedTime(this ChangeTracker changeTracker)
{
foreach (var item in changeTracker.Entries<IModificationTime>().Where(e => e.State == EntityState.Modified))
{
item.CurrentValues[AppConsts.ModificationTime] = DateTime.Now;
}
}
public static void ProcessSoftDelete(this ChangeTracker changeTracker)
{
foreach (var item in changeTracker.Entries<ISoftDelete>().Where(e => e.State == EntityState.Deleted))
{
item.State = EntityState.Modified;
item.CurrentValues[AppConsts.IsDeleted] = true;
item.CurrentValues[AppConsts.DeletionTime] = DateTime.Now;
}
}
}在服务层或控制器级别,每次都可以分配所需的值(CreatorUserId、MofidierUserId、DeleterUserId),但这成为一项常规任务,非常繁琐的。
我看过AspNetBoilerplate实现,但让我担心的是,开发人员使他们的DbContext依赖于会话和其他东西。
public abstract class AbpDbContext : DbContext, ITransientDependency, IShouldInitialize
{
public IAbpSession AbpSession { get; set; }
public IEntityChangeEventHelper EntityChangeEventHelper { get; set; }
public ILogger Logger { get; set; }
public IEventBus EventBus { get; set; }
public IGuidGenerator GuidGenerator { get; set; }
public ICurrentUnitOfWorkProvider CurrentUnitOfWorkProvider { get; set; }
public IMultiTenancyConfig MultiTenancyConfig { get; set; }
...IMHO,这是典型的违反单一责任原则。
我试着研究拦截器,但它们似乎只在实体框架的普通(非核心)版本中可用--仍然没有设法让我了解如何实现上面提到的内容。
真的,我完全不知道如何用实体框架核心来处理它。有人能想到任何服务层级别的解决方案吗?或者有更好的方法?
发布于 2018-09-01 02:53:16
这里的UserId和TenantId只是您的存储库服务(这里是DbContext)所需的数据片段。如果服务需要数据,则应该将其注入服务。
如果没有DI,您可能会在UserID和TenantID构造函数参数上设置DbContext。使用DI,您可能会对提供此数据的服务注入依赖项。
https://stackoverflow.com/questions/52124080
复制相似问题