实体框架添加重复的外键
Posted
技术标签:
【中文标题】实体框架添加重复的外键【英文标题】:Entity Framework adds duplicate foreign keys 【发布时间】:2020-07-24 20:20:24 【问题描述】:我有两个实体
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”的代码
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();
如果您想查看 Repository 类的外观:
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 方法后,我的 Extension 方法从内存列表(带有 ID 和名称)中获取符号时,从我的列表中使用的参考符号获取另一个 ID,并且在数据库中插入新符号,名称相同,但具有新 ID。
当我每次都从数据库中获取符号时,我的代码工作正常(没有在数据库中创建重复项),但我找不到我做错了什么,因为存储在列表中的符号是来自db 具有正确的 ID...
【问题讨论】:
【参考方案1】:问题是 ExistingSymbols
被加载到与保存烛台的上下文不同的 DbContext
中。
这是因为ExistingSymbols
是静态的,它用于保存烛台的多个操作。
您可以通过更改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
);
【讨论】:
您知道避免这种情况的其他解决方案吗?除了在应用程序的生命周期中使用相同的 dB 上下文以上是关于实体框架添加重复的外键的主要内容,如果未能解决你的问题,请参考以下文章