Entity Framework добавляет дубликаты внешних ключей - PullRequest
0 голосов
/ 12 апреля 2020

У меня есть две сущности

public class CandlestickData
{
    [Key]
    public int Id { get; set; }
    public virtual Symbol Symbol { get; set; }
    [Column(TypeName = "datetime2")]
    public DateTime Time { get; set; }
    public decimal Open { get; set; }
    public decimal High { get; set; }
    public decimal Low { get; set; }
    public decimal Close { get; set; }
}

и

public class Symbol
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
}

Потому что я добавляю много «CandlestickData» в БД в минуту, и символы обычно одинаковы, а символы Я не хочу использовать ненужные вызовы в БД, поэтому я сделал метод расширения, который сохраняет символы, которые уже были извлечены из БД в списке, поэтому я снова их использую.

public static class Extension
    {
        static List<Symbol> ExistingSymbols = new List<Symbol>();
        public static Symbol GetSymbolIfExistsOrCreateItInTheDb(this string name, Repository repository)
        {
            if (ExistingSymbols.Any(x => x.Name == name))
            {
                return ExistingSymbols.First(x => x.Name == name);
            }
            if (repository.SymbolExists(name))
            {
                var symbol = repository.GetSymbol(name);
                ExistingSymbols.Add(symbol);
                return symbol;
            }
            else
            {
                Symbol symbol = new Symbol { Name = name };
                repository.AddSymbol(symbol);
                symbol = repository.GetSymbol(name);
                ExistingSymbols.Add(symbol);
                return symbol;
            }
        }
    }

Это это код, который добавляет несколько 'CandlestickData' в db

using (var repository = new Repository())
            {
                var candlesticks = new List<CandlestickData>();
                foreach (var symbol in AllSymbolsTradeData[GetNotUsedIndex()])
                {
                    candlesticks.Add(new CandlestickData
                    {
                        Close = symbol.Value.Close,
                        Symbol = symbol.Key.GetSymbolIfExistsOrCreateItInTheDb(repository),
                        High = symbol.Value.High,
                        Low = symbol.Value.Low,
                        Open = symbol.Value.Open,
                        Time = symbol.Value.Time
                    });
                }
                repository.AddCandlesticksData(candlesticks);
                repository.CommitChanges();
            }

Также, если вы хотите посмотреть, как выглядит класс репозитория:

public class Repository : IDisposable
    {
        private Db context;
        public Repository()
        {
            context = new Db();
        }

        public bool SymbolExists(string name)
        {
            return context.Symbols.Where(x => x.Name == name).Any();
        }
        public Symbol GetSymbol(string name)
        {
            return context.Symbols.First(x => x.Name == name);
        }
        public void AddSymbol(Symbol symbol)
        {
            context.Symbols.Add(symbol);
            context.SaveChanges();
        }
        public void AddCandlestickData(CandlestickData candlestickData)
        {
            context.Candlesticks.Add(candlestickData);
        }
        public void AddCandlesticksData(List<CandlestickData> candlesticks)
        {
            context.Candlesticks.AddRange(candlesticks);
        }

        public void CommitChanges()
        {
            context.SaveChanges();
        }

        public void Dispose()
        {
            context.Dispose();
        }
    }

Теперь моя проблема в том, что каждый раз, когда мой Метод расширения получает символ из списка памяти (с идентификатором и именем) после того, как метод CommitChanges называется ссылочным символом, который использовался в моем списке, получает другой идентификатор, и в базу данных добавляется новый символ с тем же именем, но с новый идентификатор.

Мой код работал правильно (без создания дубликатов в БД), когда я каждый раз получал символы из БД, и я не могу найти, что я делаю неправильно поскольку символы, хранящиеся в списке, являются символами из базы данных с правильным идентификатором ...

1 Ответ

1 голос
/ 12 апреля 2020

Проблема в том, что ExistingSymbols был загружен в DbContext, отличном от контекста, который сохраняет подсвечник.

Это потому, что ExistingSymbols is stati c он используется для нескольких операций по сохранению подсвечников.

Вы можете решить эту проблему, изменив модель CandlestickData, добавив внешний ключ :

public class CandlestickData
{

    public int SymbolId { get; set; }

    [ForeignKey(nameof(SymbolId))]
    public virtual Symbol Symbol { get; set; }

, а затем использовать только внешний ключ при создании нового объекта с помощью символа:

candlesticks.Add(new CandlestickData
{
    Close = symbol.Value.Close,
    SymbolId = symbol.Key.GetSymbolIfExistsOrCreateItInTheDb(repository).Id,
    High = symbol.Value.High,
    Low = symbol.Value.Low,
    Open = symbol.Value.Open,
    Time = symbol.Value.Time
});
...