public async Task <Result> Edit(int id, [FromBody] AdminGoodsCreateRequest request)
        {
            var goods = await _goodsRepository.Query()
                        .Include(e => e.GoodsMedias)
                        .Include(e => e.Childrens).ThenInclude(e => e.OptionCombinations)
                        .Include(e => e.Childrens)
                        .Include(e => e.OptionValues).ThenInclude(e => e.Option)
                        .FirstOrDefaultAsync(e => e.Id == id);

            if (goods == null)
            {
                return(Result.Fail(ResultCodes.IdInvalid));
            }

            var goodsMedias = new List <GoodsMedia>();

            if (request.GoodsMediaIds != null && request.GoodsMediaIds.Count > 0)
            {
                foreach (var mediaId in request.GoodsMediaIds)
                {
                    goodsMedias.Add(new GoodsMedia(mediaId));
                }
            }

            goods.Name             = request.Name;
            goods.Description      = request.Description;
            goods.Price            = request.Price;
            goods.ThumbnailImageId = request.ThumbnailImageId;
            goods.DisplayOrder     = request.DisplayOrder;
            goods.CityDiscount     = request.CityDiscount;
            goods.BranchDiscount   = request.BranchDiscount;
            goods.GoodsMedias      = goodsMedias;

            if (request.IsPublished)
            {
                if (!goods.IsPublished)
                {
                    goods.IsPublished = request.IsPublished;
                    goods.PublishedOn = DateTime.Now;
                }
            }
            else
            {
                goods.PublishedOn = null;
                goods.IsPublished = false;
            }

            var optionValues = new List <GoodsOptionValue>();
            var options      = request.Options.Distinct();

            foreach (var option in options)
            {
                foreach (var item in option.Values.Distinct())
                {
                    var ov = goods.OptionValues.FirstOrDefault(c => c.OptionId == option.Id && c.Value == item.Value);
                    if (ov == null)
                    {
                        optionValues.Add(new GoodsOptionValue(option.Id, item.Value, item.DisplayOrder));
                    }
                    else
                    {
                        ov.DisplayOrder = item.DisplayOrder;
                        optionValues.Add(ov);
                    }
                }
            }
            goods.OptionValues = optionValues;

            var variations = request.Variations.Distinct();
            var childrens  = new List <Goods>();

            foreach (var variation in variations)
            {
                Goods child = null;
                if (variation.Id > 0)
                {
                    child = goods.Childrens.FirstOrDefault(e => e.Id == variation.Id);
                }

                if (child == null)
                {
                    var optionCombinations = new List <GoodsOptionCombination>();
                    var coms = variation.OptionCombinations.Distinct();
                    foreach (var combination in coms)
                    {
                        if (!goods.OptionValues.Any(c => c.OptionId == combination.OptionId))
                        {
                            return(Result.Fail(ResultCodes.RequestParamError, "商品组合中的选项不存在"));
                        }
                        if (!goods.OptionValues.Any(c => c.Value == combination.Value))
                        {
                            return(Result.Fail(ResultCodes.RequestParamError, "商品组合中的选项值不存在"));
                        }
                        if (optionCombinations.Any(c => c.OptionId == combination.OptionId && c.Value == combination.Value))
                        {
                            continue;
                        }

                        optionCombinations.Add(new GoodsOptionCombination
                        {
                            OptionId     = combination.OptionId,
                            Value        = combination.Value,
                            DisplayOrder = combination.DisplayOrder,
                            Createat     = DateTime.Now
                        });
                    }

                    child = new Goods
                    {
                        Name               = goods.Name + variation.NormalizedName,
                        NormalizedName     = variation.NormalizedName,
                        Price              = variation.Price,
                        HasOptions         = false,
                        IsVisible          = true,
                        StockQuantity      = variation.StockQuantity,
                        Createat           = DateTime.Now,
                        OptionCombinations = optionCombinations
                    };
                }
                else
                {
                    child.Name           = request.Name + variation.NormalizedName;
                    child.NormalizedName = variation.NormalizedName;
                    child.Price          = variation.Price;
                    child.StockQuantity  = variation.StockQuantity;
                }
                childrens.Add(child);
            }
            var deleteChildrens = goods.Childrens.Where(x => variations.All(c => c.Id != x.Id));

            foreach (var deleteChild in deleteChildrens)
            {
                _goodsRepository.Remove(deleteChild, false);
            }

            goods.Childrens = childrens;

            if (!goods.IsPublished)
            {
                foreach (var item in goods.Childrens.Where(e => e.IsPublished))
                {
                    item.IsPublished = false;
                    item.PublishedOn = null;
                }
            }

            _goodsRepository.Update(goods, false);

            using (var transaction = _goodsRepository.BeginTransaction())
            {
                await _goodsRepository.SaveAsync();

                transaction.Commit();
            }

            return(Result.Ok());
        }