using DocumentFormat.OpenXml.Office2010.Excel;
using Exam.Infrastructure.Data.Entity;
using Exam.Infrastructure.Data.Interface;
using Exam.Infrastructure.Enums;
using Exam.Infrastructure.Extensions;
using Exam.Repository.Sqlsugar;
using Exam.Share.ViewResponses.TestPaper;
using Hotline.Application.Exam.Core.Extensions;
using Hotline.Application.Exam.Extensions;
using Hotline.Application.Exam.Proxy;
using Hotline.Application.Exam.QueryExtensions.TestPapers;
using Hotline.Exams.TestPapers;
using Hotline.Repository.SqlSugar;
using Hotline.Repository.SqlSugar.DataPermissions;
using Hotline.Repository.SqlSugar.Exam.Core.Constants;
using Hotline.Repository.SqlSugar.Exam.Interfaces.Questions;
using Hotline.Repository.SqlSugar.Exam.Interfaces.TestPapers;
using Hotline.Repository.SqlSugar.Exam.Repositories.TestPapers;
using Hotline.Share.Dtos.Questions;
using Hotline.Share.Dtos.TestPapers;
using Hotline.Share.Dtos.Trains;
using Hotline.Share.Requests.Exam;
using Hotline.Share.Requests.TestPaper;
using Hotline.Share.Tools;
using Hotline.Share.ViewResponses.Exam;
using Hotline.Share.ViewResponses.Questions;
using JiebaNet.Segmenter.Common;
using MapsterMapper;
using Microsoft.Extensions.DependencyInjection;
using NPOI.SS.Formula.Functions;
using SqlSugar;
using System.Collections.Immutable;
using Hotline.Application.Exam.Core.Utilities;
using Hotline.Application.Exam.Interface.TestPapers;
using Hotline.Exams.ExamManages;
using Hotline.Exams.Questions;
using Hotline.Repository.SqlSugar.Exam.Repositories;
using XF.Domain.Authentications;
using XF.Domain.Dependency;
using XF.Domain.Repository;
using ExamQuestion = Hotline.Exams.Questions.ExamQuestion;
using ExamQuestionAnswer = Hotline.Exams.Questions.ExamQuestionAnswer;
using ExamQuestionKnowladge = Hotline.Exams.Questions.ExamQuestionKnowladge;
using ExamQuestionOptions = Hotline.Exams.Questions.ExamQuestionOptions;
using ExamQuestionSourceware = Hotline.Exams.Questions.ExamQuestionSourceware;
using Hotline.Repository.SqlSugar.Exam.Service;
using Hotline.Repository.SqlSugar.Exam.Extensions;

namespace Hotline.Application.Exam.Service.TestPapers
{
    public class TestPaperService : ApiService<ExamTestPaper, AddTestPaperDto, UpdateTestPaperDto, HotlineDbContext>, ITestPaperService, IScopeDependency
    {
        private readonly ITestPaperRepository _repository;
        private readonly ITestPaperItemRepository _testPaperItemRepository;
        private readonly ITestPaperRuleRepository _testPaperRuleRepository;
        private readonly ITestPaperRuleTagRepository _testPaperRuleTagRepository;
        private readonly ITestPaperItemAnswerRepository _testPaperItemAnswerRepository;
        private readonly ITestPaperItemOptionsRepository _testPaperItemOptionsRepository;
        private readonly ITestPaperItemSourcewareRepository _testPaperItemSourcewareRepository;
        private readonly ITestPaperItemKnowladgeRepository _testPaperItemKnowladgeRepository;
        private readonly IDataPermissionFilterBuilder _dataPermissionFilterBuilder;
        private readonly IServiceProvider _serviceProvider;
        private readonly ISessionContext _sessionContext;
        private readonly IMapper _mapper;
        private TestPaperProxy _testPaperProxy;

        private AddTestPaperDto _addTestPaperDto;

        public TestPaperService(ITestPaperRepository repository,
            ITestPaperRuleRepository testPaperRuleRepository,
            ITestPaperRuleTagRepository testPaperRuleTagRepository,
            ITestPaperItemRepository testPaperItemRepository,
            ITestPaperItemAnswerRepository testPaperItemAnswerRepository,
            ITestPaperItemOptionsRepository testPaperItemOptionsRepository,
            ITestPaperItemSourcewareRepository testPaperItemSourcewareRepository,
            ITestPaperItemKnowladgeRepository testPaperItemKnowladgeRepository,
            IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider,
            ISessionContext sessionContext,
            IMapper mapper) : base(repository, mapper, sessionContext)
        {
            _repository = repository;
            _testPaperItemRepository = testPaperItemRepository;
            _testPaperRuleRepository = testPaperRuleRepository;
            _testPaperRuleTagRepository = testPaperRuleTagRepository;
            this._testPaperItemAnswerRepository = testPaperItemAnswerRepository;
            this._testPaperItemOptionsRepository = testPaperItemOptionsRepository;
            this._testPaperItemSourcewareRepository = testPaperItemSourcewareRepository;
            this._testPaperItemKnowladgeRepository = testPaperItemKnowladgeRepository;
            _dataPermissionFilterBuilder = dataPermissionFilterBuilder;
            _serviceProvider = serviceProvider;
            this._sessionContext = sessionContext;
            _mapper = mapper;
        }

        #region public method
        public async Task<TestPaperDto> GetAsync(EntityQueryRequest entityQueryRequest)
        {
            var entity = await _repository.GetAsync(entityQueryRequest.Id);

            var testPaperDto = _mapper.Map<TestPaperDto>(entity);

            testPaperDto.TestPaperItemDtos = await GetTestPaperItemDtos(entityQueryRequest);

            testPaperDto.TestPaperRuleDtos = await GetTestPaperRuleDtos(entityQueryRequest);

            return testPaperDto;
        }

        public async Task<(int, List<TestPaperViewResponse>)> GetListAsync(TestPaperPagedRequest queryRequest)
        {
            queryRequest.Status = queryRequest.Status ?? Share.Enums.Exams.EPublicStatus.Valid;

            ISugarQueryable<TestPaperViewResponse> queryable = QueryResult(queryRequest);

            var result = await queryable.ToListAsync();

            var total = await queryable.CountAsync();

            return (total, result);
        }

        public async Task<PageViewResponse<TestPaperViewResponse>> GetPagedListAsync(TestPaperPagedRequest queryRequest)
        {
            ISugarQueryable<TestPaperViewResponse> queryable = QueryResult(queryRequest);

            var list = await queryable.ToPageListAsync(queryRequest.PageIndex, queryRequest.PageSize);
            var total = await queryable.CountAsync();

            var result = new TestPaperPageViewResponse
            {
                Items = list,
                Pagination = new Pagination(queryRequest.PageIndex, queryRequest.PageSize, total)
            };

            return result;
        }

        /// <summary>
        /// 新增试卷
        /// </summary>
        /// <param name="actionRequest"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task<string> AddAsync(AddTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            base.StartTran();

            var id = await base.AddAsync(actionRequest, cancellationToken);

            ResolveTestPaperId(actionRequest, id);

            base.Entity.TestPaperItems = await AddTestPaperItems(actionRequest, cancellationToken);

            var testPaperItemAnswers = await AddTestPaperItemAnswer(actionRequest, cancellationToken);

            var testPaperItemOptions = await AddTestPaperItemOptions(actionRequest, cancellationToken);

            var testPaperItemKnowlagdes = await AddTestPaperItemKnowladgeAsync(actionRequest, cancellationToken);

            var testPaperItemSourcewares = await AddTestPaperItemSourcewareAsync(actionRequest, cancellationToken);

            base.Entity.TestPaperItems.ForEach(item =>
            {
                item.TestPaperItemSourcewares = testPaperItemSourcewares.Where(x => item.Id == x.TestPaperItemId).ToList();
                item.TestPaperItemAnswers = testPaperItemAnswers.Where(x => item.Id == x.TestPaperItemId).ToList();
                item.TestPaperItemKnowlagdes = testPaperItemKnowlagdes.Where(x => item.Id == x.TestPaperItemId).ToList();
                item.TestPaperItemOptionses = testPaperItemOptions.Where(x => item.Id == x.TestPaperItemId).ToList();
            });

            //base.Entity.TestPaperRules = await AddTestPaperRules(actionRequest, cancellationToken);

            //var testPaperRuleTags = await AddTestPaperRuleTags(actionRequest, cancellationToken);

            //base.Entity.TestPaperRules?.ForEach(item =>
            //{
            //    item.TestPaperRuleTags = testPaperRuleTags.Where(m => item.Id == m.TestPaperRuleId).ToList();
            //});

            await base.Complete(base.Entity, OperationConstant.Create);

            //await GenerateTestPaper(new GenerateTestPaperRequest { TestPaperId = id }, cancellationToken);

            return id;
        }

        /// <summary>
        /// 修改试卷
        /// </summary>
        /// <param name="actionRequest"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task UpdateAsync(UpdateTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            base.StartTran();

            await base.UpdateAsync(actionRequest, cancellationToken);

            ResolveTestPaperId(actionRequest, actionRequest.Id);

            _addTestPaperDto = _mapper.Map<AddTestPaperDto>(actionRequest);

            base.Entity.TestPaperItems = await ModifyTestPaperItems(actionRequest, cancellationToken);

            var testPaperItemAnswers = await ModifyTestPaperItemAnswer(actionRequest, cancellationToken);

            var testPaperItemOptions = await ModifyTestPaperItemOptions(actionRequest, cancellationToken);

            var testPaperItemKnowlagdes = await ModifyTestPaperItemKnowladgeAsync(actionRequest, cancellationToken);

            var testPaperItemSourcewares = await ModifyTestPaperItemSourcewareAsync(actionRequest, cancellationToken);

            base.Entity.TestPaperItems.ForEach(item =>
            {
                item.TestPaperItemAnswers = testPaperItemAnswers.Where(x => item.Id == x.TestPaperItemId).ToList();
                item.TestPaperItemSourcewares = testPaperItemSourcewares.Where(x => item.Id == x.TestPaperItemId).ToList(); 
                item.TestPaperItemKnowlagdes = testPaperItemKnowlagdes.Where(x => item.Id == x.TestPaperItemId).ToList();
                item.TestPaperItemOptionses = testPaperItemOptions.Where(x => item.Id == x.TestPaperItemId).ToList();
            });

            await base.Complete(base.Entity, OperationConstant.Update);

            //await GenerateTestPaper(new GenerateTestPaperRequest { TestPaperId = actionRequest.Id }, cancellationToken);
        }


        /// <summary>
        /// 删除试卷
        /// </summary>
        /// <param name="entityQueryRequest"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public override async Task DeleteAsync(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
        {
            var testPaperRuleTags = await GetTestPaperRuleTags(entityQueryRequest);

            await base.DeleteAsync(entityQueryRequest, cancellationToken);

            var tempEntityQueryRequest = ExpressionableUtility.CreateExpression<ExamTestPaperItem>()
               .AndIF(entityQueryRequest.Id.IsNotNullOrEmpty(), x => x.TestPaperId == entityQueryRequest.Id)
               .AndIF(entityQueryRequest.Ids.IsNotNullOrEmpty(), x => entityQueryRequest.Ids.Contains(x.TestPaperId)).ToEntityQueryRequest<ExamTestPaperItem>();

            await DeleteTestPaperItems(tempEntityQueryRequest, cancellationToken);

            tempEntityQueryRequest = ExpressionableUtility.CreateExpression<ExamTestPaperRule>()
                .AndIF(entityQueryRequest.Id.IsNotNullOrEmpty(), x => x.TestPaperId == entityQueryRequest.Id)
                .AndIF(entityQueryRequest.Ids.IsNotNullOrEmpty(), x => entityQueryRequest.Ids.Contains(x.TestPaperId)).ToEntityQueryRequest<ExamTestPaperRule>();


            await DeleteTestPaperRules(tempEntityQueryRequest, cancellationToken);


            var ids = testPaperRuleTags.Select(x => x.Id).ToList();
            tempEntityQueryRequest = ExpressionableUtility.CreateExpression<ExamTestPaperRuleTag>()
                .AndIF(ids.IsNotNull(), x => ids.Contains(x.Id)).ToEntityQueryRequest<ExamTestPaperRuleTag>();

            await DeleteTestPaperRuleTags(tempEntityQueryRequest, cancellationToken);
        }

        /// <summary>
        /// 获取试卷试题数量
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<List<TestPaperQuestionCountViewResponse>> GetTestPaperQuestionCount(TestPaperQuestionCountRequest testPaperQuestionCountRequest)
        {
            var testPaperQuestionCountViewResponses = new List<TestPaperQuestionCountViewResponse>();


            if (testPaperQuestionCountRequest.TestPaperId.IsNotNullOrEmpty())
            {
                testPaperQuestionCountViewResponses = await CalcuteManualQuestionCount(testPaperQuestionCountRequest);
            }
            else if(testPaperQuestionCountRequest.ExtractRuleId.IsNotNullOrEmpty())
            {
                testPaperQuestionCountViewResponses = await CalcuteRandomQuestionCount(testPaperQuestionCountRequest);
            }
             
            return testPaperQuestionCountViewResponses;
        }


        /// <summary>
        /// 根据规则获取试题
        /// </summary>
        /// <param name="testPaperQuestionRequest"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<List<SimpleQuestionViewResponse>> GetQuestionDtos(TestPaperQuestionRequest testPaperQuestionRequest)
        {
            var questions = await GetQuestions(testPaperQuestionRequest);

            return questions;
        }

        /// <summary>
        /// 组卷
        /// </summary>
        /// <param name="generateTestPaperRequest"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task GenerateTestPaper(GenerateTestPaperRequest generateTestPaperRequest, CancellationToken cancellationToken)
        {
            var testPaper = await _repository.GetAsync(x => x.Id == generateTestPaperRequest.TestPaperId);

            if (testPaper != null)
            {
                //随机组卷
                if (testPaper.Mode == Share.Enums.Exams.EExamMode.Random)
                {
                    var questions = await GetQuestions(generateTestPaperRequest);
                    _testPaperProxy = new TestPaperProxy(_repository,
                        _testPaperItemRepository,
                        _testPaperItemAnswerRepository,
                        _testPaperItemOptionsRepository,
                        _testPaperItemSourcewareRepository,
                        _testPaperItemKnowladgeRepository,
                        _dataPermissionFilterBuilder,
                        _serviceProvider,
                        _mapper,
                        _sessionContext);

                    //删除已经生成的试卷试题
                    await _testPaperProxy.DeleteTestPaperItems(generateTestPaperRequest.TestPaperId, cancellationToken);

                    await _testPaperProxy.GenerateQuestion(questions, generateTestPaperRequest.TestPaperId, cancellationToken);
                }
            }
            
        }

        private async Task<List<SimpleQuestionViewResponse>> GetQuestions(TestPaperQuestionRequest testPaperQuestionRequest)
        {
            var questionRepository = new ExamRepository<ExamQuestion>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
            var questionTagRepository = new ExamRepository<ExamQuestionTag>(_uow, _dataPermissionFilterBuilder, _serviceProvider);

            var expression = testPaperQuestionRequest.GetExpression();
            var questionExpression = testPaperQuestionRequest.GetQuestionExpression();
            var questionTagTable = questionTagRepository.Queryable().Where(expression);
            var questionTable = questionRepository.Queryable().Where(questionExpression);

            var questions = await questionTable.LeftJoin(questionTagTable, (q, qt) => q.Id == qt.QuestionId)
                .Select((q, qt) => q).Take(testPaperQuestionRequest.Count).OrderBy(q => SqlFunc.GetRandom()).ToListAsync();

            var questionDtos = new List<SimpleQuestionViewResponse>();

            questions.ForEach(item =>
            {
                var questionDto = _mapper.Map<SimpleQuestionViewResponse>(item);
                if (questionDto != null)
                {
                    questionDtos.Add(questionDto);
                }
            });

            return questionDtos;
        }

        private async Task<List<ExamQuestion>> GetQuestions(GenerateTestPaperRequest generateTestPaperRequest)
        {
            var questionRepository = new ExamRepository<ExamQuestion>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
            var questionTagRepository = new ExamRepository<ExamQuestionTag>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
            var testPaperRuleTable = _testPaperRuleRepository.Queryable().Where(x => x.TestPaperId == generateTestPaperRequest.TestPaperId);
            var testPaperTagTable = _testPaperRuleTagRepository.Queryable();
            var questionTagTable = questionTagRepository.Queryable();
            var questionTable = questionRepository.Queryable();

            var count = await testPaperRuleTable.Select(x => x.Count).FirstAsync();

            var questions = await questionTable.LeftJoin(questionTagTable, (q, qt) => q.Id == qt.QuestionId)
                .LeftJoin(testPaperTagTable, (q, qt, tt) => qt.TagId == tt.TagId)
                .LeftJoin(testPaperRuleTable, (q, qt, tt, tpr) => tt.TestPaperRuleId == tpr.Id)
                .Where((q, qt, tt, tpr) => q.QuestionType == tpr.QuestionType)
                .Select((q, qt, tt, tpr) => q).Take(count).OrderBy(q => SqlFunc.GetRandom()).ToListAsync();


            return questions;
        }


        /// <summary>
        /// 获取标签试题数
        /// </summary>
        /// <param name="tagQuestionCountRequest"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<TagQuestionCountViewResponse> GetTagQuestionCount(TagQuestionCountRequest tagQuestionCountRequest)
        {
            var expression = tagQuestionCountRequest.GetExpression();
            var questionExpression = tagQuestionCountRequest.GetQuestionExpression();

            var tagQuestionRepository = new ExamRepository<ExamQuestionTag>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
            var quesitonRepository = new ExamRepository<ExamQuestion>(_uow, _dataPermissionFilterBuilder, _serviceProvider);

            var tagQuestionTable = tagQuestionRepository.Queryable().Where(expression);
            var questionTable = quesitonRepository.Queryable().Where(questionExpression);

            var taqQuestions = await tagQuestionTable.InnerJoin(questionTable, (t, q) => t.QuestionId == q.Id).GroupBy((t, q) => q.Id)
                .Select((t, q) =>q.Id)
                .ToListAsync();

            var result = new TagQuestionCountViewResponse
            {
                TotalCount = taqQuestions != null ? taqQuestions.Count() : 0
            };

            return result;
        }

        #endregion

        #region private method
        /// <summary>
        /// 获取查询结果
        /// </summary>
        /// <param name="queryRequest"></param>
        /// <returns></returns>
        private ISugarQueryable<TestPaperViewResponse> QueryResult(TestPaperPagedRequest queryRequest)
        {
            var expression = queryRequest.GetExpression();
            var query = _repository.Queryable().Where(expression);
            var querable = query.OrderBy(o => o.SortIndex).Select(m => new TestPaperViewResponse
            {
                Name = m.Name,
                ExamType = m.ExamType,
                Mode = m.Mode,
                Code = m.Code,
                Id = m.Id,
                Status = m.Status,
                SortIndex = m.SortIndex,
                Remark = m.Remark,
            });
            return querable;
        }


        private async Task<List<ExamTestPaperItemOptions>> ModifyTestPaperItemOptions(UpdateTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperItemDtos == null) return null;

            var questionIds = actionRequest.TestPaperItemDtos.Where(x => x.QuestionType.CheckSelectType()).Select(x => x.QuestionId).ToList();

            var entityQueryRequest = new EntityQueryRequest
            {
                Expression = ExpressionableUtility.CreateExpression<ExamTestPaperItemOptions>()
                             .AndIF(questionIds.IsNotNullOrEmpty(), x => questionIds.Contains(x.QuestionId)).ToExpression()
            };

            await DeleteTestPaperItemOptions(entityQueryRequest, cancellationToken);

            return await AddTestPaperItemOptions(_addTestPaperDto, cancellationToken);

        }

        private async Task DeleteTestPaperItemOptions(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
        {
            await _testPaperItemOptionsRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
        }

        private async Task<List<ExamTestPaperItemAnswer>> ModifyTestPaperItemAnswer(UpdateTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperItemDtos == null) return null;

            var questionIds = actionRequest.TestPaperItemDtos.Where(x => !x.QuestionType.CheckSelectType()).Select(x => x.QuestionId).ToList();

            var entityQueryRequest = new EntityQueryRequest
            {
                Expression = ExpressionableUtility.CreateExpression<ExamTestPaperItemAnswer>()
                             .AndIF(questionIds.IsNotNullOrEmpty(), x => questionIds.Contains(x.QuestionId)).ToExpression()
            };

            await DeleteTestPaperItemAnswer(entityQueryRequest, cancellationToken);

            return await AddTestPaperItemAnswer(_addTestPaperDto, cancellationToken);
        }

        private async Task DeleteTestPaperItemAnswer(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
        {
            await _testPaperItemAnswerRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
        }

        private async Task<List<ExamTestPaperRule>> AddTestPaperRules(AddTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperRuleDtos == null) return null;

            if (actionRequest.Mode == Share.Enums.Exams.EExamMode.Manual) return null;

            actionRequest.TestPaperRuleDtos.ResolveOperationStatus();

            var testPaperRuleDtos = actionRequest.TestPaperRuleDtos.Where(x => x.OperationStatus == EEOperationStatus.Add).ToList();
            var testPaperRules = _mapper.Map<List<ExamTestPaperRule>>(testPaperRuleDtos);

            testPaperRules.ToInsert(_sessionContext);


            await _testPaperRuleRepository.ValidateAddAsync(testPaperRules, cancellationToken);

            return testPaperRules;

        }

        private async Task<List<ExamTestPaperItem>> AddTestPaperItems(AddTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperItemDtos == null) return null;

            actionRequest.TestPaperItemDtos.ResolveOperationStatus();

            var testPaperItemDtos = actionRequest.TestPaperItemDtos.Where(x => x.OperationStatus == EEOperationStatus.Add).ToList();
            var testPaperItems = _mapper.Map<List<ExamTestPaperItem>>(testPaperItemDtos);
            //试题排序，为后续考试顺序出题做准备
            var index = 0;
            testPaperItems.ForEach(x =>
            {
                x.SortIndex = ++index;
            });

            testPaperItems.ToInsert(_sessionContext);


            await _testPaperItemRepository.ValidateAddAsync(testPaperItems, cancellationToken);

            return testPaperItems;
        }


        private async Task<List<ExamTestPaperRuleTag>> AddTestPaperRuleTags(AddTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperRuleDtos == null) return null;

            actionRequest.TestPaperRuleDtos.ResolveOperationStatus();

            var testPaperRuleDtos = actionRequest.TestPaperRuleDtos.Where(x => x.OperationStatus == EEOperationStatus.Add).ToList();

            var testPaperRuleTagDtos = new List<AddTestPaperRuleTagDto>();

            testPaperRuleDtos.ForEach(item =>
            {
                var testPaperRuleId = string.Empty;
                if (base.Entity != null)
                {
                    //var testPaperRule = base.Entity.TestPaperRules.FirstOrDefault(x => x.TestPaperId == item.TestPaperId
                    //&& x.QuestionType == item.QuestionType && x.Count == item.Count && x.DifficultyLevel == item.DifficultyLevel);

                    //testPaperRuleId = testPaperRule?.Id;
                }

                item.TestPaperRuleTagDtos.ForEach(x =>
                {
                    x.TestPaperRuleId = testPaperRuleId;
                });

                testPaperRuleTagDtos.AddRange(item.TestPaperRuleTagDtos);
            });


            testPaperRuleTagDtos.ResolveOperationStatus();

            var testPaperRuleTags = _mapper.Map<List<ExamTestPaperRuleTag>>(testPaperRuleTagDtos);

            testPaperRuleTags.ToInsert(_sessionContext);

            await _testPaperRuleTagRepository.ValidateAddAsync(testPaperRuleTags, cancellationToken);

            return testPaperRuleTags;
        }

        private async Task<List<ExamTestPaperRule>> ModifyTestPaperRules(UpdateTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperRuleDtos == null) return null;

            if (actionRequest.Mode == Share.Enums.Exams.EExamMode.Manual) return null;

            var all = await _testPaperRuleRepository.Queryable().Where(x => x.TestPaperId == actionRequest.Id).ToListAsync();

            actionRequest.TestPaperRuleDtos.ResolveOperationStatus(all);

            var testPaperRules = new List<ExamTestPaperRule>();

            testPaperRules.AddRangeExt(await AddTestPaperRules(actionRequest, cancellationToken));

            testPaperRules.AddRangeExt(await UpdateTestPaperRules(actionRequest,all, cancellationToken));

            var entityQueryRequest = ExpressionableUtility.CreateExpression<ExamTestPaperRule>()
                .AndIF(actionRequest.Id.IsNotNullOrEmpty(), x => x.TestPaperId == actionRequest.Id).ToEntityQueryRequest<ExamTestPaperRule>();

            await DeleteTestPaperRules(entityQueryRequest, cancellationToken);

            return testPaperRules;
        }

        private async Task DeleteTestPaperRules(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
        {
            await _testPaperRuleRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
        }

        private async Task<List<ExamTestPaperRule>> UpdateTestPaperRules(UpdateTestPaperDto actionRequest,List<ExamTestPaperRule> all, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperRuleDtos == null) return null;

            var testPaperRuleDtos = actionRequest.TestPaperRuleDtos.Where(x => x.OperationStatus == EEOperationStatus.Update).ToList();

            var ids = testPaperRuleDtos.Select(x => x.Id);

            var testPaperRules = all.Where(x => ids.Contains(x.TestPaperId)).ToList();

            var entities = new List<ExamTestPaperRule>();

            foreach (var testPaperRuleDto in testPaperRuleDtos)
            {
                var entity = testPaperRules.FirstOrDefault(x => x.Id == testPaperRuleDto.Id);

                entity = _mapper.Map(testPaperRuleDto, entity);

                entity.TestPaperId = actionRequest.Id;
            }

            entities.ToUpdate(_sessionContext);

            await _testPaperRuleRepository.ValidateUpdateAsync(entities, cancellationToken);

            return entities;

        }

        private async Task<List<ExamTestPaperRuleTag>> ModifyTestPaperRuleTags(UpdateTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperRuleDtos == null) return null;

            var ruleIds = actionRequest.TestPaperRuleDtos.Select(x => x.Id);

            var all = await _testPaperRuleTagRepository.Queryable().Where(x => ruleIds.Contains(x.TestPaperRuleId)).ToListAsync();

            actionRequest.TestPaperRuleDtos.ResolveOperationStatus(all);

            var testPaperRuleTags = new List<ExamTestPaperRuleTag>();

            testPaperRuleTags.AddRangeExt(await AddTestPaperRuleTags(actionRequest, cancellationToken));

            testPaperRuleTags.AddRangeExt(await UpdateTestPaperRuleTags(actionRequest, all, cancellationToken));

            var ids = actionRequest.TestPaperRuleDtos.Where(x => x.OperationStatus == EEOperationStatus.Delete).Select(x => x.Id).ToList();

            var entityQueryRequest = ExpressionableUtility.CreateExpression<ExamTestPaperRuleTag>()
                .AndIF(ids.IsNullOrEmpty(), x => ids.Contains(x.TestPaperRuleId)).ToEntityQueryRequest<ExamTestPaperRuleTag>();

            await DeleteTestPaperRuleTags(entityQueryRequest, cancellationToken);

            return testPaperRuleTags;
        }

        private async Task DeleteTestPaperRuleTags(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
        {
            await _testPaperRuleTagRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
        }

        private async Task<List<ExamTestPaperRuleTag>> UpdateTestPaperRuleTags(UpdateTestPaperDto actionRequest,List<ExamTestPaperRuleTag> all, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperRuleDtos == null) return null;

            var ruleIds = actionRequest.TestPaperRuleDtos.Where(x => x.OperationStatus == EEOperationStatus.Update).Select(x => x.Id).ToList();

            var testPaperRuleTags = all.Where(x => ruleIds.Contains(x.TestPaperRuleId)).ToList();

            var entities = new List<ExamTestPaperRuleTag>();

            foreach (var testPaperRuleTagDto in actionRequest.TestPaperRuleDtos.SelectMany(x=>x.TestPaperRuleTagDtos))
            {
                var entity = testPaperRuleTags.FirstOrDefault(x => x.Id == testPaperRuleTagDto.Id);

                entity = _mapper.Map<UpdateTestPaperRuleTagDto, ExamTestPaperRuleTag>(testPaperRuleTagDto,entity);
            }

            entities.ToUpdate(_sessionContext);

            await _testPaperRuleTagRepository.ValidateUpdateAsync(entities, cancellationToken);

            return entities;
        }

        private async Task<List<ExamTestPaperItem>> ModifyTestPaperItems(UpdateTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperItemDtos == null) return null;

            var all = await _testPaperItemRepository.Queryable().Where(x => x.TestPaperId == actionRequest.Id).ToListAsync();

            actionRequest.TestPaperItemDtos.ResolveOperationStatus(all);

            var testPaperItems = new List<ExamTestPaperItem>();

            testPaperItems.AddRangeExt(await AddTestPaperItems(_addTestPaperDto, cancellationToken));

            testPaperItems.AddRangeExt(await UpdateTestPaperItems(actionRequest,all, cancellationToken));

            var entityQueryRequest = ExpressionableUtility.CreateExpression<ExamTestPaperItem>()
                .AndIF(actionRequest.Id.IsNotNullOrEmpty(), x => x.TestPaperId == actionRequest.Id).ToEntityQueryRequest<ExamTestPaperItem>();

            await DeleteTestPaperItems(entityQueryRequest, cancellationToken);

            return testPaperItems;
        }

        private async Task DeleteTestPaperItems(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
        {
            await _testPaperItemRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
        }

        private async Task<List<ExamTestPaperItem>> UpdateTestPaperItems(UpdateTestPaperDto actionRequest,List<ExamTestPaperItem> all, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperItemDtos == null) return null;

            var testPaperItemDtos = actionRequest.TestPaperItemDtos.Where(x => x.OperationStatus == EEOperationStatus.Update).ToList();

            var ids = testPaperItemDtos.Select(x => x.Id);

            var testPaperItems = all.Where(x => ids.Contains(x.TestPaperId)).ToList();

            var entities = new List<ExamTestPaperItem>();

            foreach (var testPaperItemDto in testPaperItemDtos)
            {
                var entity = testPaperItems.FirstOrDefault(x => x.Id == testPaperItemDto.Id);

                entity = _mapper.Map(testPaperItemDto, entity);

                entity.TestPaperId = actionRequest.Id;
            }

            entities.ToUpdate(_sessionContext);

            await _testPaperItemRepository.ValidateUpdateAsync(entities, cancellationToken);

            return entities;
        }

        /// <summary>
        /// 获取试卷规则
        /// </summary>
        /// <param name="entityQueryRequest"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private async Task<List<TestPaperRuleDto>> GetTestPaperRuleDtos(EntityQueryRequest entityQueryRequest)
        {
            var testPaperRuleTable = _testPaperRuleRepository.Queryable().Where(x => x.TestPaperId == entityQueryRequest.Id);

            var testPaperRuleTags = await GetTestPaperRuleTags(entityQueryRequest);

            var queryable = testPaperRuleTable.Select(t => new TestPaperRuleDto
            {
                Id = t.Id,
                TestPaperId = t.TestPaperId,
                Count = t.Count,
                DifficultyLevel = t.DifficultyLevel,
                SortIndex = t.SortIndex,
                QuestionType = t.QuestionType,
            });

            var testPaperRuleTagDtos = _mapper.Map<List<TestPaperRuleTagDto>>(testPaperRuleTags);
            var testPaperRuleList = await queryable.ToListAsync();
            testPaperRuleList.ForEach(x => x.TestPaperRuleTagDtos = testPaperRuleTagDtos.Where(n => n.TestPaperRuleId == x.Id).ToList());

            return testPaperRuleList;

        }

        private async Task<List<TestPaperItemDto>> GetTestPaperItemDtos(EntityQueryRequest entityQueryRequest)
        {
            var testPaperRuleTable = _testPaperItemRepository.Queryable().Where(x => x.TestPaperId == entityQueryRequest.Id);


            var queryable = testPaperRuleTable.Select(t => new TestPaperItemDto
            {
                Id = t.Id,
                QuestionId = t.QuestionId,
                DifficultyLevel = t.DifficultyLevel,
                Title = t.Title,
                TestPaperId = t.TestPaperId,
                QuestionType = t.QuestionType
            });

            return await queryable.ToListAsync();

        }

        private void ResolveTestPaperId(AddTestPaperDto actionRequest, string id)
        {
            actionRequest.TestPaperRuleDtos?.ForEach(x =>
            {
                x.TestPaperId = id;
            });

            actionRequest.TestPaperItemDtos?.ForEach(x => x.TestPaperId = id);
        }

        private void ResolveTestPaperId(UpdateTestPaperDto actionRequest, string id)
        {
            actionRequest.TestPaperRuleDtos?.ForEach(x =>
            {
                x.TestPaperId = id;
            });

            actionRequest.TestPaperItemDtos?.ForEach(x => x.TestPaperId = id);
        }

        private async Task<List<ExamTestPaperRuleTag>> GetTestPaperRuleTags(EntityQueryRequest entityQueryRequest)
        {
            var expression = entityQueryRequest.GetTestPaperRuleExpression();
            var testPageRuleTable = _testPaperRuleRepository.Queryable().Where(expression);
            var testPageRuleTagTable = _testPaperRuleTagRepository.Queryable();

            var query = testPageRuleTagTable.InnerJoin(testPageRuleTable, (t, r) => t.TestPaperRuleId == r.Id).Select((t, r) => t);

            return await query.ToListAsync();
        }

        private async Task<List<TestPaperQuestionCountViewResponse>> CalcuteRandomQuestionCount(TestPaperQuestionCountRequest testPaperQuestionCountRequest)
        {
            var testPaperQuestionCountViewResponses = new List<TestPaperQuestionCountViewResponse>();
            var extractRuleRepository = new ExamRepository<ExamExtractRule>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
            var ruleTagRepository = new ExamRepository<ExamRuleTag>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
            var tagQuestionRepository = new ExamRepository<ExamTagQuestion>(_uow, _dataPermissionFilterBuilder, _serviceProvider);


            var expression = testPaperQuestionCountRequest.GetExpression();
            var exatractTable = extractRuleRepository.Queryable().Where(expression);
            var ruleTagTable = ruleTagRepository.Queryable();
            var tagQuestionTable = tagQuestionRepository.Queryable();


            var testPaperRules = await exatractTable.InnerJoin(ruleTagTable, (e, rt) => e.Id == rt.RuleId)
                .InnerJoin(tagQuestionTable, (e, rt, tq) => rt.RuleId == tq.RuleId && rt.TagId == tq.TagId)
                .GroupBy((e, rt, tq) => tq.QuestionType)
                .Select((e, rt, tq) => new ExamTagQuestion
                {
                    QuestionType = tq.QuestionType,
                    Count = SqlFunc.AggregateSum(tq.Count)
                }).MergeTable().Where(m => m.Count > 0)
                .ToListAsync();

            if (testPaperRules != null)
            {
                testPaperRules.ForEach(x => testPaperQuestionCountViewResponses.Add(new TestPaperQuestionCountViewResponse
                {
                    QuestionType = x.QuestionType,
                    Count = x.Count
                }));
            }

            return testPaperQuestionCountViewResponses;
        }

        private async Task<List<TestPaperQuestionCountViewResponse>> CalcuteManualQuestionCount(TestPaperQuestionCountRequest testPaperQuestionCountRequest)
        {
            var testPaperQuestionCountViewResponses = new List<TestPaperQuestionCountViewResponse>();

            var expression = testPaperQuestionCountRequest.GetTestPaperItemsExpression();

            var testPaperItemTable =  _testPaperItemRepository.Queryable().Where(expression);

            testPaperQuestionCountViewResponses = await testPaperItemTable.GroupBy(t=>t.QuestionType).Select(t => new TestPaperQuestionCountViewResponse
                {
                    QuestionType = t.QuestionType,
                    Count = SqlFunc.AggregateCount(t.Id)
                }).ToListAsync();           


            return testPaperQuestionCountViewResponses;
        }



        private async Task<List<ExamTestPaperItemOptions>> AddTestPaperItemOptions(AddTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            var questionOptionRepository = new ExamRepository<ExamQuestionOptions>(_uow, _dataPermissionFilterBuilder, _serviceProvider);

            var quesitonIds = actionRequest.TestPaperItemDtos.Select(x => x.QuestionId);

            var questionOptions = await questionOptionRepository.Queryable().Where(x => quesitonIds.Contains(x.QuestionId)).ToListAsync();

            var testPaperItemOptions = new List<ExamTestPaperItemOptions>();

            actionRequest.TestPaperItemDtos.Where(x => x.QuestionType.CheckSelectType()).ToList().ForEach(x =>
            {
                var testPaperItem = base.Entity?.TestPaperItems.FirstOrDefault(n => n.QuestionId == x.QuestionId) ?? null;

                var options = questionOptions.Where(n => x.QuestionId == n.QuestionId).ToList();

                if (options != null)
                {
                    options.ForEach(item =>
                    {
                        var testPaperItemOption = _mapper.Map<ExamQuestionOptions, ExamTestPaperItemOptions>(item);

                        testPaperItemOption.TestPaperItemId = testPaperItem?.Id;

                        testPaperItemOption.QuestionOptionId = item.Id;

                        testPaperItemOption.ToInsert(_sessionContext);

                        testPaperItemOptions.Add(testPaperItemOption);
                    });
                }

            });

            await _testPaperItemOptionsRepository.ValidateAddAsync(testPaperItemOptions, cancellationToken);

            return testPaperItemOptions;
        }

        private async Task<List<ExamTestPaperItemAnswer>> AddTestPaperItemAnswer(AddTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            var questionOptionRepository = new ExamRepository<ExamQuestionAnswer>(_uow, _dataPermissionFilterBuilder, _serviceProvider);

            var quesitonIds = actionRequest.TestPaperItemDtos?.Select(x => x.QuestionId);            

            var questionAnswer = await questionOptionRepository.Queryable().Where(x => quesitonIds.Contains(x.QuestionId)).ToListAsync();

            var testPaperItemAnswers = new List<ExamTestPaperItemAnswer>();

            actionRequest.TestPaperItemDtos.Where(x => !x.QuestionType.CheckSelectType()).ToList().ForEach(x =>
            {
                var testPaperItem = base.Entity?.TestPaperItems.FirstOrDefault(n => n.QuestionId == x.QuestionId) ?? null;

                var options = questionAnswer.Where(n => x.QuestionId == n.QuestionId).ToList();

                options.ForEach(item =>
                {
                    var testPaperItemAnswer = _mapper.Map<ExamQuestionAnswer, ExamTestPaperItemAnswer>(item);

                    testPaperItemAnswer.TestPaperItemId = testPaperItem?.Id;

                    testPaperItemAnswer.QuestionAnswerId = item.Id;

                    testPaperItemAnswer.ToInsert(_sessionContext);

                    testPaperItemAnswers.Add(testPaperItemAnswer);
                });
            });

            await _testPaperItemAnswerRepository.ValidateAddAsync(testPaperItemAnswers, cancellationToken);

            return testPaperItemAnswers;
        }




        private async Task<List<ExamTestPaperItemSourceware>> AddTestPaperItemSourcewareAsync(AddTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            var questionSourcewareRepository = new ExamRepository<ExamQuestionSourceware>(_uow, _dataPermissionFilterBuilder, _serviceProvider);

            var quesitonIds = actionRequest.TestPaperItemDtos.Select(x => x.QuestionId);

            var questionSourceware = await questionSourcewareRepository.Queryable().Where(x => quesitonIds.Contains(x.QuestionId)).ToListAsync();

            var testPaperItemSourcewares = new List<ExamTestPaperItemSourceware>();

            actionRequest.TestPaperItemDtos.Where(x => x.QuestionType.CheckSelectType()).ToList().ForEach(x =>
            {
                var testPaperItem = base.Entity?.TestPaperItems.FirstOrDefault(n => n.QuestionId == x.QuestionId) ?? null;

                var options = questionSourceware.Where(n => x.QuestionId == n.QuestionId).ToList();

                if (options != null)
                {
                    options.ForEach(item =>
                    {
                        var testPaperItemSourceware = _mapper.Map<ExamQuestionSourceware, ExamTestPaperItemSourceware>(item);

                        testPaperItemSourceware.TestPaperItemId = testPaperItem?.Id;

                        testPaperItemSourceware.ToInsert(_sessionContext);

                        testPaperItemSourcewares.Add(testPaperItemSourceware);
                    });
                }
            });

            await _testPaperItemSourcewareRepository.ValidateAddAsync(testPaperItemSourcewares, cancellationToken);

            return testPaperItemSourcewares;
        }

        private async Task<List<ExamTestPaperItemKnowladge>> AddTestPaperItemKnowladgeAsync(AddTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            var questionKnowladgeRepository = new ExamRepository<ExamQuestionKnowladge>(_uow, _dataPermissionFilterBuilder, _serviceProvider);

            var quesitonIds = actionRequest.TestPaperItemDtos.Select(x => x.QuestionId);

            var questionKnowladge = await questionKnowladgeRepository.Queryable().Where(x => quesitonIds.Contains(x.QuestionId)).ToListAsync();

            var testPaperItemKnowladges = new List<ExamTestPaperItemKnowladge>();

            actionRequest.TestPaperItemDtos.Where(x => x.QuestionType.CheckSelectType()).ToList().ForEach(x =>
            {
                var testPaperItem = base.Entity?.TestPaperItems.FirstOrDefault(n => n.QuestionId == x.QuestionId) ?? null;

                var options = questionKnowladge.Where(n => x.QuestionId == n.QuestionId).ToList();

                if (options != null)
                {
                    options.ForEach(item =>
                    {
                        var testPaperItemKnowladge = _mapper.Map<ExamQuestionKnowladge, ExamTestPaperItemKnowladge>(item);

                        testPaperItemKnowladge.TestPaperItemId = testPaperItem?.Id;

                        testPaperItemKnowladge.ToInsert(_sessionContext);

                        testPaperItemKnowladges.Add(testPaperItemKnowladge);
                    });
                }
            });

            await _testPaperItemKnowladgeRepository.ValidateAddAsync(testPaperItemKnowladges, cancellationToken);

            return testPaperItemKnowladges;
        }

        private async Task<List<ExamTestPaperItemSourceware>> ModifyTestPaperItemSourcewareAsync(UpdateTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperItemDtos == null) return null;

            var questionIds = actionRequest.TestPaperItemDtos.Where(x => x.QuestionType.CheckSelectType()).Select(x => x.QuestionId).ToList();

            var entityQueryRequest = new EntityQueryRequest
            {
                Expression = ExpressionableUtility.CreateExpression<ExamTestPaperItemSourceware>()
                             .AndIF(questionIds.IsNotNullOrEmpty(), x => questionIds.Contains(x.QuestionId)).ToExpression()
            };

            await DeleteTestPaperItemSourcewareAsync(entityQueryRequest, cancellationToken);

           return  await AddTestPaperItemSourcewareAsync(_addTestPaperDto, cancellationToken);
        }

        private async Task DeleteTestPaperItemSourcewareAsync(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
        {
            await _testPaperItemSourcewareRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
        }

        private async Task<List<ExamTestPaperItemKnowladge>> ModifyTestPaperItemKnowladgeAsync(UpdateTestPaperDto actionRequest, CancellationToken cancellationToken)
        {
            if (actionRequest.TestPaperItemDtos == null) return null;

            var questionIds = actionRequest.TestPaperItemDtos.Where(x => x.QuestionType.CheckSelectType()).Select(x => x.QuestionId).ToList();

            var entityQueryRequest = new EntityQueryRequest
            {
                Expression = ExpressionableUtility.CreateExpression<ExamTestPaperItemKnowladge>()
                             .AndIF(questionIds.IsNotNullOrEmpty(), x => questionIds.Contains(x.QuestionId)).ToExpression()
            };

            await DeleteTestPaperItemKnowladgeAsync(entityQueryRequest, cancellationToken);

            return await AddTestPaperItemKnowladgeAsync(_addTestPaperDto, cancellationToken);
        }

        private async Task DeleteTestPaperItemKnowladgeAsync(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
        {
            await _testPaperItemKnowladgeRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
        }
        #endregion

        #region protected method
        protected override async Task CompleteAdd(ExamTestPaper entity)
        {
            await base.AddNav(entity)
                  //.Include(x => x.TestPaperRules)
                  //.ThenInclude(x => x.TestPaperRuleTags)
                  .Include(x => x.TestPaperItems)
                  .ThenInclude(x => x.TestPaperItemAnswers)
                  .Include(x => x.TestPaperItems, new InsertNavOptions
                  {
                      OneToManyIfExistsNoInsert = true
                  })
                  .ThenInclude(x => x.TestPaperItemOptionses)
                  .Include(x => x.TestPaperItems, new InsertNavOptions
                  {
                      OneToManyIfExistsNoInsert = true
                  })
                  .ThenInclude(x => x.TestPaperItemKnowlagdes)
                  .Include(x => x.TestPaperItems, new InsertNavOptions
                  {
                      OneToManyIfExistsNoInsert = true
                  })
                  .ThenInclude(x => x.TestPaperItemSourcewares).ExecuteCommandAsync();
        }

        protected override async Task CompleteUpdate(ExamTestPaper entity)
        {
            await base.UpdateNav(entity)
                 //.Include(x => x.TestPaperRules)
                 //.ThenInclude(x => x.TestPaperRuleTags)
                 .Include(x => x.TestPaperItems)
                 .ThenInclude(x => x.TestPaperItemAnswers)
                 .Include(x => x.TestPaperItems, new UpdateNavOptions
                 {
                     OneToManyInsertOrUpdate = true
                 })
                 .ThenInclude(x => x.TestPaperItemOptionses)
                 .Include(x => x.TestPaperItems, new UpdateNavOptions
                 {
                     OneToManyInsertOrUpdate = true
                 })
                 .ThenInclude(x => x.TestPaperItemKnowlagdes)
                 .Include(x => x.TestPaperItems, new UpdateNavOptions
                 {
                     OneToManyInsertOrUpdate = true
                 })
                 .ThenInclude(x => x.TestPaperItemSourcewares).ExecuteCommandAsync();
        }
        #endregion
    }
}
