在使用UnitofWork和async完成先前的异步操作之前,在此上下文中启动了第二个操作

时间:2018-04-07 11:44:07

标签: c# asp.net-web-api async-await repository-pattern unit-of-work

在上一次异步操作完成之前,在此上下文中启动了第二个操作。使用'等待'确保在调用此上下文中的另一个方法之前已完成任何异步操作。不保证任何实例成员都是线程安全的。

我的单位工作代码

 public class UnitOfWork : IUnitOfWork
    {
        private readonly CAMSDbEntities _context;
        private bool _disposed;
        public Dictionary<Type, object> repositories = new Dictionary<Type, object>();
        private Guid _objectId;

        public UnitOfWork(IContextFactory contextFactory)
        {
            _context = contextFactory.DbContext as CAMSDbEntities;
            _objectId = Guid.NewGuid();
        }

        public IGenericRepository<T> Repository<T>() where T : class
        {
            if (repositories.Keys.Contains(typeof(T)) == true)
            {
                return repositories[typeof(T)] as GenericRepository<T>;
            }
            GenericRepository<T> repo = new GenericRepository<T>(_context);
            repositories.Add(typeof(T), repo);
            return repo;
        }

我的统一配置

      container.RegisterType<IHttpContext, HttpContextObject>();
                container.RegisterType<IDataBaseManager, DataBaseManager>();
                container.RegisterType<IContextFactory, ContextFactory>();

                container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<>));

                container.RegisterType<IUnitOfWork, UnitOfWork>();

                container.RegisterType<IAnalytics, DashbordService>();
    GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);

webApi控制器

 public class DashbordController : ApiController
        {
            private static IAnalytics _analytics;
            public DashbordController(IAnalytics dashbordService)
            {
                _analytics = dashbordService;
            }

            [HttpGet]
            [Route("GetStudentAssessmentHistory")]
            public IHttpActionResult GetStudentAssessmentHistory(int studentID)
            {
                var result = _analytics.GetStudentAssessmentHistoryGraphData(studentID);
                return Ok(result);
            }

            [HttpGet]
            [Route("GetStudentFeePaymentHistory")]
            public async Task<IHttpActionResult> GetStudentFeePaymentData(int studentID)
            {
                var result = await _analytics.GetStudentFeePaymentData(studentID);
                return Ok(result);
            }

            [HttpGet]
            [Route("GetLedgerHitoryByDepartment")]
            public async Task<IHttpActionResult> GetLedgerHitoryByDepartment(int schoolID, int departmentId)
            {
                var result = await _analytics.GetLedgerHitory(schoolID, departmentId);
                return Ok(result);
            }

            [HttpGet]
            [Route("GetLedgerExpenseTrendByDepartment")]
            public async Task<IHttpActionResult> GetLedgerExpenseTrendByDepartment(int schoolID)
            {
                var result = await _analytics.GetLedgerExpenseTrend(schoolID);
                return Ok(result);
            }

dashboardservice代码

  public async Task<List<LedgerExpense>> GetLedgerExpenseTrend(int schoolId)
        {
            try
            {
                var ledgerExpenses = new List<LedgerExpense>();
                var currentDate = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, INDIAN_ZONE);
                DateTime previoYearDate = currentDate.AddYears(-1);
                var ledgerPayments = await  _unitOfWork.Repository<LedgerDetail>().GetManyAsync(x => x.SchoolID == schoolId && x.PaymentDate <= currentDate
                                                       && x.PaymentDate >= previoYearDate);

                foreach (var ledgerPayment in ledgerPayments.OrderBy(x => x.PaymentDate).GroupBy(y => y.DepartmentID))
                {
                    var department = await  _unitOfWork.Repository<DeptartmentType>().GetAsync(x => x.ID == ledgerPayment.Key);

                    var ledgerData = new LedgerExpense
                    {
                        Department = department.DepartmentName,
                        TotalLedgerExpense = 0
                    };

                    foreach (var departmentPayment in ledgerPayment)
                    {
                        ledgerData.TotalLedgerExpense += departmentPayment.TotalPaidAmount;
                    }

                    ledgerExpenses.Add(ledgerData);
                }

                return ledgerExpenses;
            }
            catch (Exception ex)
            {
                logger.Log("An error occurred while fetching ledger expenses");
                return null;
            }
        }

我在仪表板服务代码中实现了类似的异步方法。每当我请求仪表板UI时,所有请求都会同时到达同一个控制器,并逐个为每个请求创建unitofwork和dbcontext的新对象。它有时完美地工作但有时我认为unitofwork和dbcontext对象流动错误的线程并抛出此错误。我认为它选择了错误的dbcontext,它已经忙于仪表板服务的其他api请求。

1 个答案:

答案 0 :(得分:0)

请从以下代码中删除控制器中的static关键字:

try-with-resources

创建之后,除非应用程序池被回收(手动或IIS重新启动等),否则永远不会再创建它。由于您对所有请求使用相同的实例,因此您将随机获得该错误。如果请求在下一个请求到达之前完成,则 NOT 将导致错误。否则它会。因此,不总是得到错误的原因(如你在问题中提到的那样)。

请阅读try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } 如何影响网络方案(或服务器)中的设计。

尝试将Web请求视为单个事务,为每个请求创建所有类,然后在提供请求后将其丢弃。这意味着如果您有private static IAnalytics _analytics;` 或任何其他用于共享的机制,它将在请求之间共享。