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

时间:2019-10-21 13:38:57

标签: c# asp.net-core entity-framework-core

我正在尝试构建控制器以检查数据库中是否已经存在实体(StockData),如果不存在,请添加它。否则,不应添加它。但是,我构建的代码总是添加它,我不明白为什么。

我正在尝试构建一个应用程序(ASP.NET Core MVC,使用SQL Server和EF Core),该应用程序从API加载库存数据并将其显示在页面上。在这种情况下,我想避免保存StockData的重复实体,否则我的数据库将在每次调用时不断填充已经存在的数据。

这是我的控制器以及我的Product和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; }
    }

2 个答案:

答案 0 :(得分:1)

如果找到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);
    }

答案 1 :(得分:0)

我相信我发现了造成重复问题的原因。

foreach方法实际上可以很好地工作,禁止根据if语句的条件向数据库添加新库存。

但是,由于某种原因,product.Data = stocks;是通过某种方式自动 添加了product.Data(即从API中新获取的stocks集合)到数据库,即使没有任何明确的方法也可以。

我不确定为什么会这样,但是我重构了代码以使用临时库存清单(tempStocks)来避免将整个获取的stocks集合添加到{{1 }},像这样:

product.Data

可能不是最优雅的解决方案,但我希望它能帮助遇到同样问题的人。