C# EF Core向数据库添加重复实体
我正在尝试构建我的控制器,以检查数据库中是否已经存在实体(StockData),如果不存在,则添加它。否则,不应添加。然而,我构建的代码总是在添加它,我不明白为什么 我正在尝试构建一个应用程序(ASP.NET Core MVC,使用SQL Server和EF Core),从API加载股票数据并将其显示在页面上。虽然这样做有效,但我希望避免保存重复的StockData实体,否则每次调用时,我的数据库都会不断填充已有的数据 以下是我的控制器以及我的产品和StockData类:C# EF Core向数据库添加重复实体,c#,asp.net-core,entity-framework-core,C#,Asp.net Core,Entity Framework Core,我正在尝试构建我的控制器,以检查数据库中是否已经存在实体(StockData),如果不存在,则添加它。否则,不应添加。然而,我构建的代码总是在添加它,我不明白为什么 我正在尝试构建一个应用程序(ASP.NET Core MVC,使用SQL Server和EF Core),从API加载股票数据并将其显示在页面上。虽然这样做有效,但我希望避免保存重复的StockData实体,否则每次调用时,我的数据库都会不断填充已有的数据 以下是我的控制器以及我的产品和StockData类: {
{
private readonly ApplicationDbContext dbContext;
public StockController(ApplicationDbContext dbContext)
{
this.dbContext = dbContext;
}
public IActionResult Index()
{
var symbol = "MSFT";
var name = "Microsoft";
Product product;
if(dbContext.Products.Any(p => p.Symbol == symbol))
{
product = dbContext.Products.FirstOrDefault(p => p.Symbol == symbol);
}
else
{
product = new Product
{
Symbol = symbol,
Name = name
};
dbContext.Add(product);
}
dbContext.SaveChanges();
var apiResponse = $"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol={symbol}&interval=5min&apikey=APIKEY&datatype=csv".GetStringFromUrl();
var stocks = apiResponse.FromCsv<List<StockData>>().ToList();
product.Data = stocks;
foreach (var stock in product.Data)
{
if(!dbContext.StockData.Any(s => s.Timestamp.Equals(stock.Timestamp) && s.ProductId.Equals(product.ProductId)))
{
dbContext.Add(stock);
}
}
dbContext.SaveChanges();
return View(product);
}
}
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public string Symbol { get; set; }
public string Description { get; set; }
public List<StockData> Data { get; set; }
}
public class StockData
{
[Ignore]
public int StockDataId { get; set; }
[Ignore]
public int ModelId { get; set; }
[Ignore]
public int ProductId { get; set; }
public string Timestamp { get; set; }
public string Open { get; set; }
public string High { get; set; }
public string Low { get; set; }
public string Close { get; set; }
public string Volume { get; set; }
}
{
私有只读应用程序dbContext dbContext;
公共库存控制器(ApplicationDbContext dbContext)
{
this.dbContext=dbContext;
}
公共IActionResult索引()
{
var symbol=“MSFT”;
var name=“Microsoft”;
产品;
if(dbContext.Products.Any(p=>p.Symbol==Symbol))
{
product=dbContext.Products.FirstOrDefault(p=>p.Symbol==Symbol);
}
其他的
{
产品=新产品
{
符号=符号,
Name=Name
};
添加(产品);
}
dbContext.SaveChanges();
var apiResponse=$”https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol={symbol}&interval=5min&apikey=apikey&datatype=csv.GetStringFromUrl();
var stocks=apiResponse.FromCsv().ToList();
产品数据=股票;
foreach(var库存产品数据)
{
if(!dbContext.StockData.Any(s=>s.Timestamp.Equals(stock.Timestamp)&&s.ProductId.Equals(product.ProductId)))
{
添加(股票);
}
}
dbContext.SaveChanges();
返回视图(产品);
}
}
公共类产品
{
public int ProductId{get;set;}
公共字符串名称{get;set;}
公共字符串符号{get;set;}
公共字符串说明{get;set;}
公共列表数据{get;set;}
}
公共类股票数据
{
[忽略]
public int StockDataId{get;set;}
[忽略]
公共int ModelId{get;set;}
[忽略]
public int ProductId{get;set;}
公共字符串时间戳{get;set;}
公共字符串Open{get;set;}
公共字符串高位{get;set;}
公共字符串低位{get;set;}
公共字符串Close{get;set;}
公共字符串卷{get;set;}
}
如果找到Id,则应更新记录,否则应添加Id
private readonly ApplicationDbContext dbContext;
public StockController(ApplicationDbContext dbContext)
{
this.dbContext = dbContext;
}
public IActionResult Index()
{
var symbol = "MSFT";
var name = "Microsoft";
Product product;
product = dbContext.Products.FirstOrDefault(p => p.Symbol.Equals(symbol));
if (product == null)
{
dbContext.Add(new Product() { Symbol = symbol, Name = name });
}
else
{
dbContext.Entry(product).State = EntityState.Modified;
}
dbContext.SaveChanges();
var apiResponse = $"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol={symbol}&interval=5min&apikey=APIKEY&datatype=csv".GetStringFromUrl();
var stocks = apiResponse.FromCsv<List<StockData>>().ToList();
product.Data = stocks;
foreach (var stock in product.Data)
{
var newStock = dbContext.StockData.FirstOrDefault(s => s.ProductId.Equals(product.ProductId));
if (!dbContext.StockData.Any(s => s.Timestamp.Equals(stock.Timestamp)))
{
if (newStock == null)
{
dbContext.Add(stock);
}
else
{
dbContext.Entry(stock).State = EntityState.Modified;
}
dbContext.SaveChanges();
}
}
return View(product);
}
private只读应用程序dbContext dbContext;
公共库存控制器(ApplicationDbContext dbContext)
{
this.dbContext=dbContext;
}
公共IActionResult索引()
{
var symbol=“MSFT”;
var name=“Microsoft”;
产品;
product=dbContext.Products.FirstOrDefault(p=>p.Symbol.Equals(Symbol));
如果(产品==null)
{
添加(新产品(){Symbol=Symbol,Name=Name});
}
其他的
{
dbContext.Entry(product.State=EntityState.Modified;
}
dbContext.SaveChanges();
var apiResponse=$”https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol={symbol}&interval=5min&apikey=apikey&datatype=csv.GetStringFromUrl();
var stocks=apiResponse.FromCsv().ToList();
产品数据=股票;
foreach(var库存产品数据)
{
var newStock=dbContext.StockData.FirstOrDefault(s=>s.ProductId.Equals(product.ProductId));
如果(!dbContext.StockData.Any(s=>s.Timestamp.Equals(stock.Timestamp)))
{
if(newStock==null)
{
添加(股票);
}
其他的
{
dbContext.Entry(stock.State=EntityState.Modified;
}
dbContext.SaveChanges();
}
}
返回视图(产品);
}
我相信我找到了导致复制问题的原因
foreach
方法实际上运行良好,根据if
语句的条件禁止向数据库中添加新股
但是,由于某种原因,product.Data=股票
以某种方式自动将product.Data
即从API中新获取的stocks
集合添加到数据库中,即使没有任何明确的方法也可以这样做
我不知道为什么会发生这种情况,但我重构了代码,改为使用临时库存列表(tempStocks
),以避免将整个获取的stocks
集合添加到产品中。数据
,如下所示:
var apiResponse = $"https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol={symbol}&interval=1min&apikey=APIKEY&datatype=csv&outputsize=full".GetStringFromUrl();
var tempStocks = apiResponse.FromCsv<List<StockData>>().ToList();
var newStocks = new List<StockData>();
foreach (var stock in tempStocks)
{
if (!dbContext.StockData.Any(s => s.Timestamp == stock.Timestamp && s.ProductId == product.ProductId))
{
newStocks.Add(stock);
}
dbContext.SaveChanges();
}
product.Data = newStocks;
var-apiResponse=$”https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol={symbol}&interval=1min&apikey=apikey&datatype=csv&outputsize=full“.GetStringFromUrl();
var tempStocks=apiResponse.FromCsv().ToList();
var newStocks=新列表();
foreach(临时股票中的var股票)
{
if(!dbContext.StockData.Any(s=>s.Timestamp==stock.Timestamp&&s.ProductId==product.ProductId))
{
添加(股票);
}
dbContext.SaveChanges();
}
product.Data=newStocks;
可能不是最优雅的解决方案,但我希望它能帮助遇到同样问题的人。是否保存了重复的库存或产品?你认为复制品是什么?你的问题可能与时间戳有关。如果(!dbContext.StockData.Any(s=>s.Timestamp.Equals(stock.Timestamp)和&s.ProductId.Equals(product.ProductId)))Dupl