Экземпляр объекта типа ‘Sport’ не может быть отслежен, потому что другой экземпляр со значением ключа

#c# #entity-framework

#c# #entity-framework

Вопрос:

Я знаю, что есть много подобных проблем, но ни одна из них мне не помогла. Я получаю события из внешнего API, в котором есть вид спорта (в котором много лиг). Но когда я добавляю события, если спорт уже существует, он выдает ошибку, указанную в названии. Должен ли я фильтровать его вручную, как это делается с событиями?

  public class Sport: IDbEntity
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Id { get; set; }
        public string Name { get; set; }
        public virtual ICollection<Event> Events  { get; set; }
        public virtual ICollection<League> Leagues { get; set; }
    }

public class Event: IDbEntity
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; }

    public string HomeTeam { get; set; }
    public string AwayTeam { get; set; }
    public DateTime Date { get; set; }

    public virtual League League { get; set; }
    public int LeagueId { get; set; }

    public virtual Sport Sport { get; set; }
    public int SportId { get; set; }

    public virtual ICollection<Prediction> Predictions { get; set; }
    public virtual ICollection<Market> Markets { get; set; }

}

    public async Task FetchEvents()
    {
        var root = await "https://bwin-odds.p.rapidapi.com/v1/bwin/prematch?sport_id=4"
                 .WithHeader("X-RapidAPI-Host", "bwin-odds.p.rapidapi.com")
                 .WithHeader("X-RapidAPI-Key", "..")
                 .GetJsonAsync<Root>();

        List<Event> events = mapper.Map<List<Event>>(root.results).Take(10).ToList();
           
               //current working solution I found
                   var sports = events
            .Select(e => e.Sport)
            .GroupBy(s => s.Id)
            .Select(x => x.FirstOrDefault())
            .ToList();

        var leagues = events
            .Select(e => e.League)
            .GroupBy(l => l.Id)
            .Select(x => x.FirstOrDefault())
            .ToList();

        await sportRepository.AddRange(sports);
        await leagueRepository.AddRange(leagues);
        
        foreach(Event e in events)
        {
            e.Sport = null;
            e.League = null;
        }

        await eventRepository.AddRange(events);
    }

        CreateMap<Event, Result>().ReverseMap()
            .BeforeMap( (src, dest) =>
            {
                if (src.Markets != null)
                {
                    src.Markets = new List<BwinMarket>() { src.Markets.First() };
                }
            })
            .AfterMap( (src, dest) =>
            {
                dest.SportId = src.SportId;
                dest.LeagueId = src.LeagueId;

                dest.League.SportId = src.SportId;

                dest.Sport.Id = src.SportId;
                dest.League.Id = src.LeagueId;

                if (src.Markets != null)
                {
                    dest.Markets.FirstOrDefault().EventId = int.Parse(src.Id);
                }
            });

    public async Task AddRange(ICollection<T> entities)
    {
        var records = await _context.Set<T>().ToListAsync();
        var entitiesToAdd = entities.Where(entity => !records.Any(record => record.Id == entity.Id));

        await _context.Set<T>().AddRangeAsync(entitiesToAdd);
        await _context.SaveChangesAsync();
    }
  

Комментарии:

1. Это ошибка, потому что вы пытаетесь добавить в свою базу данных sport с тем же идентификатором, что и у существующей записи sport?

2. Я не уверен, но, похоже, у вас есть опечатка в вашем AddRange методе. Вместо добавления объектов await _context.Set<T>().AddRangeAsync(entities); , которые вы, возможно, захотите добавить entitiesToAdd .

3. Да, это было раньше entitiesToAdd , просто пробовал разные варианты, не работает. Я также попытался добавить лиги и виды спорта отдельно (добавил код в edit), та же проблема.

4. вы пытались добавить только sports? Я имею в виду без этих двух вызовов await leagueRepository.AddRange(leagues); await eventRepository.AddRange(events); . Просто чтобы узнать, работает ли это.

5. Кстати, как разрешен ваш _context объект?