C# EF Core向数据库添加重复实体

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类: {

我正在尝试构建我的控制器,以检查数据库中是否已经存在实体(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