SaveChanges()并添加到数据库不起作用

时间:2019-04-08 15:03:27

标签: asp.net-mvc entity-framework autofac

我正在努力将实体框架添加到我们的Web应用程序asp.net MVC 5中,但是我很难保存更改并添加到数据库中。我使用通用的BaseRepository设置了UnitOfWork,并且尝试了一些尝试来使其正常工作。首先,我以为我可以使用AutoFac将我的仓库注入UnitOfWork,就像这样

public UnitOfWork(IServiceItem serviceItem
        , ITechServiceItem techServiceItem
        , ITechnicianTime technicianTime
        , ISproc sproc
        , IRepairOrder repairOrder
        , ICustomer customer
         , IRepairOrderStatus repairOrderStatus
        , IRepairOrderUnit repairOrderUnit
        , IFiles files
        , IPartInventory partInventory
        , IRepairOrderItems repairOrderItems
        )
        {
            RepairOrderItems = repairOrderItems;
            PartInventory = partInventory;
            Files = files;
            RepairOrderUnit = repairOrderUnit;
            RepairOrderStatus = repairOrderStatus;
            RepairOrder = repairOrder;
            Customer = customer;
            Sproc = sproc;
            ServiceItem = serviceItem;
            TechServiceItem = techServiceItem;
            TechnicianTime = technicianTime;
        }

我的BaseRepo就像

public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        protected DataDbContext _db;

       public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        protected DataDbContext _db;

        internal void GetData()
        {
            if (_db == null)
            {
                string accountNumber = HttpContext.Current.User.Identity.GetCompanyAccountNumber();
                var connectionToken = ConfigurationManager.AppSettings["LoginSplitToken"];
                _db = new DataDbContext(ConfigurationManager.ConnectionStrings["NameOfConnString"].ConnectionString.Replace(connectionToken, accountNumber));
            }
        }

        public TEntity Get(int id)
        {
            return _db.Set<TEntity>().Find(id);
        }

        public IEnumerable<TEntity> GetAll()
        {
            return _db.Set<TEntity>().ToList();
        }

        public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
        {
            return _db.Set<TEntity>().Where(predicate);
        }

        public void Add(TEntity entity)
        {
            _db.Set<TEntity>().Add(entity);
        }

        public void AddRange(IEnumerable<TEntity> entities)
        {
            _db.Set<TEntity>().AddRange(entities);
        }

        public void Remove(TEntity entity)
        {
            _db.Set<TEntity>().Remove(entity);
        }

        public void RemoveRange(IEnumerable<TEntity> entities)
        {
            _db.Set<TEntity>().RemoveRange(entities);
        }

        public int CompleteData()
        {
            return _db.SaveChanges();
        }

        public TEntity Get(int id)
        {
            return _db.Set<TEntity>().Find(id);
        }

        public IEnumerable<TEntity> GetAll()
        {
            return _db.Set<TEntity>().ToList();
        }

        public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
        {
            return _db.Set<TEntity>().Where(predicate);
        }

        public void Add(TEntity entity)
        {
            _db.Set<TEntity>().Add(entity);
        }

        public void AddRange(IEnumerable<TEntity> entities)
        {
            _db.Set<TEntity>().AddRange(entities);
        }

        public void Remove(TEntity entity)
        {
            _db.Set<TEntity>().Remove(entity);
        }

        public void RemoveRange(IEnumerable<TEntity> entities)
        {
            _db.Set<TEntity>().RemoveRange(entities);
        }

        public int CompleteData()
        {
            return _db.SaveChanges();
        }
}

和我的StartUp.Configuration

 public void Configuration(IAppBuilder app)
        {
            var builder = new ContainerBuilder();
            HttpConfiguration config = GlobalConfiguration.Configuration;

            // REGISTER DEPENDENCIES
            builder.RegisterType<EverLogicDbContext>().AsSelf().InstancePerRequest();
            builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
            builder.RegisterType<ApplicationSignInManager>().AsSelf().InstancePerRequest();
            builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerRequest();
            builder.Register(c => HttpContext.Current.User).InstancePerRequest();
            builder.Register(c => app.GetDataProtectionProvider()).InstancePerRequest();

            builder.RegisterType<ApplicationUserStore>().As<IUserStore<EverLogicMamber, int>>()
                  .WithParameter(new TypedParameter(typeof(ISecurityOfWork), new SecurityOfWork(new SecurityDbContext())))
                .InstancePerRequest();

            //Database
            builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();
            builder.RegisterType<SecurityOfWork>().As<ISecurityOfWork>().InstancePerRequest();
            //Service
            builder.RegisterType<TechnicianTimeService>().As<ITechnicianTimeService>().InstancePerRequest();
            builder.RegisterType<PartService>().As<IPartService>().InstancePerRequest();
            builder.RegisterType<TechServiceItemService>().As<ITechServiceItemService>().InstancePerRequest();
            //Repo
            builder.RegisterType<Company>().As<ICompany>().InstancePerRequest();
            builder.RegisterType<Views>().As<IViews>().InstancePerRequest();

            builder.RegisterType<RepairOrderItems>().As<IRepairOrderItems>().InstancePerRequest();
            builder.RegisterType<PartInventory>().As<IPartInventory>().InstancePerRequest();
            builder.RegisterType<Files>().As<IFiles>().InstancePerRequest();
            builder.RegisterType<TechDashboardService>().As<ITechDashboardService>().InstancePerRequest();
            builder.RegisterType<RepairOrderUnit>().As<IRepairOrderUnit>().InstancePerRequest();
            builder.RegisterType<RepairOrderStatus>().As<IRepairOrderStatus>().InstancePerRequest();
            builder.RegisterType<Customer>().As<ICustomer>().InstancePerRequest();
            builder.RegisterType<ServiceItem>().As<IServiceItem>().InstancePerRequest();
            builder.RegisterType<RepairOrder>().As<IRepairOrder>().InstancePerRequest();
            builder.RegisterType<Sproc>().As<ISproc>().InstancePerRequest();
            builder.RegisterType<TechServiceItem>().As<ITechServiceItem>().InstancePerRequest();
            builder.RegisterType<TechnicianTime>().As<ITechnicianTime>().InstancePerRequest();

            // REGISTER CONTROLLERS SO DEPENDENCIES ARE CONSTRUCTOR INJECTED
            builder.RegisterControllers(typeof(MvcApplication).Assembly);
            builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
            builder.RegisterWebApiFilterProvider(config);
            builder.RegisterWebApiModelBinderProvider();

            var container = builder.Build();

            // REPLACE THE MVC DEPENDENCY RESOLVER WITH AUTOFAC
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            app.UseAutofacMiddleware(container);
            app.UseAutofacMvc();
            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

            ConfigureAuth(app);
        }

但是通过此设置,数据库不会更新或添加新实体。 然后,我尝试从UnitOfWork移除Dependcy注入,并将UnitOfWork设置为

 protected DataDbContext _db;
      public UnitOfWork(DataDbContext context)
        {
            GetData();
            RepairOrderItems = new RepairOrderItems(_db);
            PartInventory = new PartInventory(_db);
            Files = new Files(_db);
            RepairOrderUnit = new RepairOrderUnit(_db);
            RepairOrderStatus = new RepairOrderStatus(_db);
            RepairOrder = new RepairOrder(_db);
            Customer = new Customer(_db);
            Sproc = new Sproc(_db);
            ServiceItem = new ServiceItem(_db);
            TechServiceItem = new TechServiceItem(_db);
            TechnicianTime = new TechnicianTime(_db);
        }
  internal void GetData()
        {
            if (_db == null)
            {
                string accountNumber = HttpContext.Current.User.Identity.GetCompanyAccountNumber();
                var connectionToken = ConfigurationManager.AppSettings["LoginSplitToken"];
                _db = new DataDbContext(ConfigurationManager.ConnectionStrings["NameOfConnString"].ConnectionString.Replace(connectionToken, accountNumber));
            }
        }

,然后将SaveChanges从BaseRepo移到UnitOfWork,但是仍然没有任何内容正在保存或添加到数据库中。 我想念什么??

1 个答案:

答案 0 :(得分:1)

TL; DR 问题是您所有的存储库都使用单独的独立DbContexts,因此注入到DbContext中的UnitOfWork没有待处理的更改当您在其上调用SaveChanges时,这就是为什么您看不到数据库的任何更改。

为了使工作单元正常运行,您的UnitOfWork类以及代码执行数据持久化所需的所有存储库类都必须共享相同的DbContext实例。在您的代码中,很明显,每个存储库都有一个工厂方法来创建自己的独立DbContext实例。

  • GetData()类中删除BaseRepository工厂方法,而是要求由AutoFac将EverLogicDbContext实例的一个实例注入到BaseRepository的构造函数中。这将要求您所有的存储库子类也需要具有接受相同的EverLogicDbContext的构造函数。
  • 根据您的上一次编辑,UnitOfWork类必须接受存储库使用的相同共享EverLogicDbContext。由于您已经标记了asp.net-mvc,因此RequestPerInstance的生存期范围对于您的情况是正确的。
  • 您的UnitOfWork类需要控制SaveChanges(Async)方法,因此从CompleteData类中删除BaseRepository方法。
  • 您似乎已经做过,DbContext需要注册InstancePerRequest

builder.RegisterType<EverLogicDbContext>().AsSelf().InstancePerRequest();

如果所有这些都正确地绑在一起:

  • 在处理每个请求期间,AutoFac将在您的具体DbContext实例第一次创建。
  • 然后,所有存储库将在请求的生存期内共享相同的DbContext实例,并且DbContext将跟踪您的服务所做的临时更改。
  • 注入到您的主要“业务逻辑”(例如,控制器或Orchestrator / Handler)中的UnitOfWork将能够Commit通过简单地在共享计算机上调用SaveChangesAsync来执行的操作。 DbContext。这一切都将在单个数据库连接下发生,因此将是轻量级的事务。

根据上面的其他评论,IMO实体框架已经是内置了事务支持的已经很高级的框架,因此,如果所有ACID活动都将针对同一数据库进行,则过度设计“ UnitOfWork”模式毫无意义。 (并且可以包装到同一DbContext中。)