简体   繁体   中英

Aspnet core Parallels operation DbContext problem

I've a problem when I use Pararrel function in aspnetcore, in particular when in the cycle i try to save something in database. I get my data from externarl api and deseserialize it in my class. This is the Parallel code.

Root players = JsonConvert.DeserializeObject<Root>(responseStream);
var bulkhead = Policy.BulkheadAsync(10, Int32.MaxValue);
var tasks = new List<Task>();
foreach (var player in players.players)
                    {

                        var t = bulkhead.ExecuteAsync(async () =>
                        {
            
                            int wyId = Convert.ToInt32(player.wyId);
                            HttpRequestMessage secondRequest = createRequest("https://apirest.com/v2/players/" + wyId + "?details=currentTeam&imageDataURL=true");
                            var client2 = _clientFactory.CreateClient();
                            var response2 = await client2.SendAsync(secondRequest);
                            if (response2.IsSuccessStatusCode)
                            {
                                var responseStream2 = await response2.Content.ReadAsStringAsync();
                                dynamic playerFullDetails = JsonConvert.DeserializeObject<dynamic>(responseStream2);
                                int wyId2 = Convert.ToInt32(playerFullDetails.wyId);
                                int marketValue = 0;
                                HttpRequestMessage tirthRequest = createRequest("https://apirest.com/v2/players/" + wyId2 + "/marketvalue");
                                var client3 = _clientFactory.CreateClient();
                                var response3 = await client3.SendAsync(tirthRequest);
                                if (response3.IsSuccessStatusCode)
                                {
                                    var responseStream3 = await response3.Content.ReadAsStringAsync();
                                    dynamic marketValueResponse = JsonConvert.DeserializeObject<dynamic>(responseStream3);
                                    if (marketValueResponse.marketValue != 0)
                                    {
                                        marketValue = Convert.ToInt32(marketValueResponse.marketValue);
                                    }
                                }
                                DateTime birthday = Convert.ToDateTime(playerFullDetails.birthDate);
                                int age = DateTime.Now.Year - birthday.Year;
                                Player finalPlayer = new Player();
                                finalPlayer.PlayerId = wyId2;
                                finalPlayer.MarketValue = marketValue;
                                finalPlayer.Value = Convert.ToDouble(marketValue) / Convert.ToDouble(1000000);
                                finalPlayer.Firstname = playerFullDetails.firstName;
                                finalPlayer.Lastname = playerFullDetails.lastName;
                                finalPlayer.Name = playerFullDetails.shortName;
                                finalPlayer.Position = playerFullDetails.role.name;
                                finalPlayer.Height = playerFullDetails.height;
                                finalPlayer.Foot = playerFullDetails.foot;
                                finalPlayer.IsLocked = false;
                                finalPlayer.Team = playerFullDetails.currentTeam != null ? playerFullDetails.currentTeam.name : "";
                                finalPlayer.TeamId = playerFullDetails.currentTeam != null ? playerFullDetails.currentTeam.wyId : 0;
                                finalPlayer.CompetitionId = 524;
                                finalPlayer.UpdatedDay = DateTime.Now;
                                finalPlayer.League = "Serie A";
                                finalPlayer.Age = age;

                                Player playerExist = await _context.Player.Where(x => x.PlayerId == wyId2).SingleOrDefaultAsync();

                                if (playerExist == null)
                                {
                                    if (finalPlayer.TeamId != 0)
                                    {
                                        await _context.Player.AddAsync(finalPlayer);
                                        await _context.SaveChangesAsync();
                                    }
                                }

                                if (finalPlayer.TeamId != 0)
                                {
                                    Team teamExist = await _context.Team.Where(x => x.TeamId == finalPlayer.TeamId).SingleOrDefaultAsync();
                                    if (teamExist == null)
                                    {
                                        Team team = new Team();
                                        team.TeamId = finalPlayer.TeamId;
                                        team.TeamName = finalPlayer.Team;
                                        await _context.Team.AddAsync(team);
                                        await _context.SaveChangesAsync();
                                    }
                                }
                            }
                        });
                        tasks.Add(t);
                    }
                    await Task.WhenAll(tasks);

The function isert 50/60 (in total would be 500) element in db and finally i receive this error

A second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913 .

Thanks

It's best practice to use 1 dbcontext per unit of work, and the dbcontext is not thread safe

So either create a new dbcontext per thread or lock access with someting like a semaphore otherwise you will always get unstable code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM