Внедрить ChangeTracker в конструктор - PullRequest
0 голосов
/ 02 октября 2018

Я хотел бы повторно использовать концепцию, которую мы внедрили в другой проект с ядром asp.net.Зарегистрированные IEntityMetadataProvider s будут вызываться DbContext перед сохранением объекта со следующим кодом:

public class SppdContext : DbContext
{
    private readonly IEnumerable<IEntityMetadataProvider> _entityMetadataProviders;

    public SppdContext(DbContextOptions<SppdContext> options, IEnumerable<IEntityMetadataProvider> entityMetadataProviders) : base(options)
    {
        _entityMetadataProviders = entityMetadataProviders;
    }

    public override int SaveChanges()
    {
        PrepareSaveChanges();
        return base.SaveChanges();
    }

    private void PrepareSaveChanges()
    {
        ChangeTracker.DetectChanges();
        SetModifierMetadataOnChangedEntities();
    }

    private void SetModifierMetadataOnChangedEntities()
    {
        foreach (var entityMetadataProvider in _entityMetadataProviders)
        {
            entityMetadataProvider.SetModifierMetadataOnChangedEntities();
        }
    }
}

-

public class EntityMetadataProvider : IEntityMetadataProvider
{
    private readonly ChangeTracker _changeTracker;

    public EntityMetadataProvider(ChangeTracker changeTracker)
    {
        _changeTracker = changeTracker;
    }

    public void SetModifierMetadataOnChangedEntities()
    {
        var entriesToSetModifier = _changeTracker.Entries<BaseEntity>().Where(e => HasToSetModifierMetadata(e.State)).ToList();

        if (entriesToSetModifier.Count > 0)
        {
            var saveDate = DateTime.UtcNow;

            foreach (var entryToSetModifier in entriesToSetModifier)
            {
                SetModifierMetadataProperties(entryToSetModifier, saveDate);
            }
        }
    }

    private static bool HasToSetModifierMetadata(EntityState state)
    {
        return state == EntityState.Added || state == EntityState.Modified;
    }

    private static void SetModifierMetadataProperties(EntityEntry<BaseEntity> entry, DateTime saveDate)
    {
        if (entry.State == EntityState.Added)
        {
            entry.Property(e => e.CreatedOn).CurrentValue = saveDate;
        }
        else
        {
            entry.Property(e => e.CreatedOn).IsModified = false;
        }
    }
}

DbContext регистрируется следующим образом:

var connectionString = "Data Source=.\\SQLEXPRESS; Initial Catalog=Sppd; Integrated Security=true; MultipleActiveResultSets=True;";
services.AddDbContext<SppdContext>(options => options.UseSqlServer(connectionString));

В этой реализации я получаю следующее исключение при var context = serviceScope.ServiceProvider.GetRequiredService<SppdContext>();:

Unable to resolve service for type 'Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker' while attempting to activate 'SppdDocs.Infrastructure.DbAccess.EntityMetadataProvider'.

Как мне зарегистрировать ChangeTracker, чтобы его можно было ввести?

1 Ответ

0 голосов
/ 02 октября 2018

Если я правильно понимаю, вы хотите искать изменения в трекере изменений SppdContext.

Невозможно получить трекер изменений путем инъекции.Он принадлежит экземпляру вашего контекста.Вы должны передать Changetracker при вызове метода вместо конструктора.

в классе SpddContext вы получите

private void SetModifierMetadataOnChangedEntities()
{
    foreach (var entityMetadataProvider in _entityMetadataProviders)
    {
        entityMetadataProvider.SetModifierMetadataOnChangedEntities(ChangeTracker);
    }
}

и в EntityMetaDataProvider:

public class EntityMetadataProvider : IEntityMetadataProvider
{

    public EntityMetadataProvider()
    {       
    }

    public void SetModifierMetadataOnChangedEntities(ChangeTracker changeTracker)
    {
        var entriesToSetModifier = changeTracker.Entries<BaseEntity>().Where(e => 
HasToSetModifierMetadata(e.State)).ToList();

        if (entriesToSetModifier.Count > 0)
        {
            var saveDate = DateTime.UtcNow;

            foreach (var entryToSetModifier in entriesToSetModifier)
            {
                SetModifierMetadataProperties(entryToSetModifier, saveDate);
            }
        }
    }
...
...