简体   繁体   English

EF Core-自动设置字段值

[英]EF Core - set field values automatically

I'm developing a web app using ASP.NET Core + Entity Framework Core . 我正在使用ASP.NET Core + Entity Framework Core开发一个Web应用程序。

I'd like to store more info regarding creation , modification & deletion . 我想存储有关创建修改删除的更多信息。

My EF entities implement interfaces which bring the following fields: 我的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; }

I've been trying to make my app set all of the fields automatically . 我一直在尝试让我的应用自动设置所有字段。

Right now I am only able to handle the DateTime fields: 现在,我只能处理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;
        }
    }
}

At a Service Layer or Controller level it is possible to assign the required value each time ( CreatorUserId , MofidierUserId , DeleterUserId ) but this becomes a routine task, very tedious . 服务层控制器级别,可以每次分配所需的值( CreatorUserIdMofidierUserIdDeleterUserId ),但这成为例行任务, 非常繁琐

I've seen the AspNetBoilerplate implementation , but what worries me about it is that the developers make their DbContext dependent on Session and other stuff. 我已经看过AspNetBoilerplate实现 ,但是让我担心的是,开发人员使他们的DbContext依赖于Session和其他东西。

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, this is a typical violation of Single Responsibility Principle . 恕我直言,这是对单一责任原则的典型违反

I tried looking into interceptors , but they seem to be available only in ordinary (non-core) edition of Entity Framework - still haven't managed to get my head around how to implement what I mentioned above. 我尝试研究拦截器 ,但是它们似乎仅在普通(非核心)版本的Entity Framework中可用-仍然无法使我领悟如何实现上述功能。

Really, I'm completely lost as to how to handle it with Entity Framework Core. 确实,我完全不知道如何使用Entity Framework Core处理它。 Can anyone think of any Service Layer level solution for that? 谁能想到任何服务层级别的解决方案? Or maybe there's a better way? 还是有更好的方法?

UserId and TenantId here are just pieces of data that your repository service (here a DbContext) needs. 这里的UserId和TenantId只是您的存储库服务(这里是DbContext)所需的数据。 If a service needs data, it should be injected into the service. 如果服务需要数据,则应将其注入服务中。

Without DI you might make UserID and TenantID constructor parameters on your DbContext. 没有DI,您可能会在DbContext上设置UserID和TenantID构造函数参数。 With DI you might inject a dependency on a service that provides this data. 使用DI,您可能会注入对提供此数据的服务的依赖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM