如何通过DbContext访问Facade接口?

问题描述 投票:0回答:1

我有一个棘手的问题,如果有人帮助我解决这个问题那就太好了。 有一个用于修改实体的外观类,我想在发生操作时获取用户的操作并将其存储在 UsersActionsLog 实体中:

 public class UsersActionsLog
    {
        [Key]
        public long Id { get; set; }
        public long UserId { get; set; }
        public string Entity { get; set; }
        public string? PrimaryKeyValue { get; set; }
        public string PropertyName { get; set; }
        public string OldValue { get; set; }
        public string NewValue { get; set; }
        public string Action { get; set; } // [0]=Added [1]=Modified [2]=Deleted
        public bool Successful { get; set; } // [false]= failed [true]=successful
        public DateTime Date { get; set; } = DateTime.Now;
    }

我正在使用门面模式来执行代码。 我的服务:

    public class RequestPostUserActionLogServiceDto
    {
        public long UserId { get; set; }
        public string Entity { get; set; }
        public string? PrimaryKeyValue { get; set; }
        public string PropertyName { get; set; }
        public string OldValue { get; set; }
        public string NewValue { get; set; }
        public string Action { get; set; } // [0]=Added [1]=Modified [2]=Deleted
        public bool Successful { get; set; } // [false]= failed [true]=successful
    }
    public interface IPostUserActionLogService
    {
        bool Execute(RequestPostUserActionLogServiceDto req);
    }
    public class PostUserActionLogService: IPostUserActionLogService
    {
        private readonly IDataBaseContext _context;
        public PostUserActionLogService(IDataBaseContext context)
        {
            _context = context;
        }
        public bool Execute(RequestPostUserActionLogServiceDto req)
        {
            return true;
        }
    }

我的门面:

 public class UserActionsLogFacade: IUserActionLogFacade
    {
        private readonly IDataBaseContext _context;
        public UserActionsLogFacade(IDataBaseContext context)
        {
            _context = context;
        }
        ///////////////////////////////////// PostUserActionLogService
        private PostUserActionLogService _postUserActionLogService;
        public PostUserActionLogService PostUserActionLogService
        {
            get { return _postUserActionLogService = _postUserActionLogService ?? new PostUserActionLogService(_context); }
        }
    }

和:

    public interface IUserActionLogFacade
    {
        public PostUserActionLogService PostUserActionLogService { get;}
    }

我试图在“DataBaseContext”中注入“ISerActionLogFacade”,但遇到错误[检测到类型服务的循环依赖关系] enter image description here

    public class DataBaseContext : DbContext, IDataBaseContext
    {
        private IUserActionLogFacade _userActionLogFacade;
        public DataBaseContext(DbContextOptions option, IUserActionLogFacade userActionLogFacade) : base(option)
        {
            _userActionLogFacade = userActionLogFacade;
        }

        // Tables
        public DbSet<Users> Users { get; set; } // Users Table
        public DbSet<Roles> Roles { get; set; } // Roles Table
        public DbSet<UsersInRoles> UsersInRoles { get; set; } // UsersInRoles Table
        public DbSet<UsersActionsLog> UsersActionsLog { get; set; } // UsersActionsLog Table

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //> FLuent API of Entity Configurations
            //---- Users
            modelBuilder.ApplyConfiguration(new UsersConfigurations());
            //---- ROles
            modelBuilder.ApplyConfiguration(new RolesConfigurations());
            //< End
        }
        public override int SaveChanges()
        {
            var modifiedEntries = ChangeTracker.Entries()
                .Where(
                    e =>
                    e.State == EntityState.Modified ||
                    e.State == EntityState.Added ||
                    e.State == EntityState.Deleted
                    );


            foreach (var entry in modifiedEntries)
            {
                var entityType = entry.Context.Model.FindEntityType(entry.Entity.GetType());
                var inserted = entityType.FindProperty("InsertDate");
                var updated = entityType.FindProperty("UpdateDate");
                var deleted = entityType.FindProperty("DeleteDate");

                switch (entry.State)
                {
                    case EntityState.Added:
                        if (inserted != null) entry.Property("InsertDate").CurrentValue = DateTime.Now;
                        break;
                    case EntityState.Modified:
                        if (updated != null) entry.Property("UpdateDate").CurrentValue = DateTime.Now;
                        break;
                    case EntityState.Deleted:
                        if (deleted != null) entry.Property("DeleteDate").CurrentValue = DateTime.Now;
                        entry.State = EntityState.Modified;
                        break;
                }


                _userActionLogFacade.PostUserActionLogService.Execute( new RequestPostUserActionLogServiceDto 
                {
                    Entity = entry.Entity.GetType().Name, //entityName 
                    Action = "",
                    NewValue = "",
                    OldValue = "",
                    PrimaryKeyValue = "1",
                    PropertyName = "",
                    Successful = true,
                    UserId = 1,
                });
            }
            return base.SaveChanges();
        }
    }

当然,我看到了这个问题:我看到了这个问题:DbContext Override SaveChanges not fire但问题是,基于该问题,回答者直接解决了问题。我的意思是,由于 CLEAN ARCHITATURE 结构,我们不能直接在 PERSISTENCE 层中使用 DOMIAN 层。 那么,如何在 OVERRIED SAVECHANGE() 方法中注入外观并使用其服务?

asp.net-mvc entity-framework clean-architecture savechanges
1个回答
0
投票

当涉及到审计和错误记录到数据库之类的事情时,我使用的解决方案是有界 DbContext。基本上,对于您的审计外观,不要使用 DataBaseContext,而是创建类似 RequestActionDbContext 的内容,它仅定义此 RequestAction 实体,并注入到 DataBaseContext 中以在拦截的 SaveChanges() 上调用。这避免了循环依赖问题,并确保使用 SaveChanges() 保存 RequestAction 不会触发无限递归堆栈溢出。

这种方法的缺点是,保存被跟踪的实体和保存审计记录这两个操作是独立的,因此如果一个操作失败,另一个操作不会回滚。因此,如果这很重要,那么就需要手动协调。通常,我会按照正常方式在 SaveChanges() 期间设置外观 DTO,然后将它们提交到外观(在调用

base.SaveChanges()
后使用 RequestActionDbContext 编写:

var result = base.SaveChanges();
try
{
    _userActionLogFacade.PostUserActionLogService.Execute(requestActionDto);
}
catch (Exception ex)
{
     // Log exception... Save succeeded but audit failed...
}
return result;

它并不完美,但 IMO 覆盖了 99.95%。如果审核电话失败,则发生了严重或异常的情况,我想手动调查并处理该情况。

© www.soinside.com 2019 - 2024. All rights reserved.