【问题标题】:EF6 update record result in referential integrity constraint exceptionEF6 更新记录导致参照完整性约束异常
【发布时间】:2016-02-01 20:54:22
【问题描述】:

我有一个多对一关系的模型:

类股票

public class Stock
{
  [Key, Column(Order = 0)]
  [DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
  public int StockId { get; set; }

  [Key, Column(Order = 1)]
  [ForeignKey("Description")]
  public string Code { get; set; }

  public StockDescription Description { get; set; }

  [Required]
  [DisplayName("# Shares")]
  public int NumberOfShares { get; set; }

  public void UpdateStock(AddOperationViewModel viewModel)
  {
     this.NumberOfShares += viewModel.NumberOfShares;
     //Get some information from Yahoo!
     Controllers.DetailedInfosStocksController controller = new controllers.DetailedInfosStocksController();
     Models.DetailedQuoteQueryResultModel infos = controller.RetrieveStockDetailedInfos(this.Code);
     FillInfos(infos);
  }

  public void FillInfos(DetailedQuoteQueryResultModel infos)
  {
     if(Description == null)
     {
        Description = new StockDescription();
        Description.Code = infos.Symbol;
        Description.Name = infos.Name;
     }
     Description.FillInfos(infos);
  }
}

类 StockDescription

public class StockDescription
{ 
  [Key, Column(Order = 1)]
  public string Code { get; set; }

  [Required]
  public string Name { get; set; }

  [DisplayFormat(DataFormatString = "{0:F2}")]
  [DisplayName("Price")]
  public double LastPrice { get; set; }

  [DisplayFormat(DataFormatString = "{0:P2}")]
  [DisplayName("Variation")]
  public double ChangePercent { get; set; }

  public void FillInfos(DetailedQuoteQueryResultModel infos)
  {
     LastPrice = double.Parse(infos.LastTradePriceOnly);
     ChangePercent = double.Parse(infos.ChangeinPercent.Replace("%", "")) / 100;
  }
}

我正在尝试按如下方式更新股票条目:

  // POST: AddOperation
  [HttpPost]
  public ActionResult AddOperation(AddOperationViewModel viewModel)
  {
     if(ModelState.IsValid)
     {
        var existingStock = db.Stocks.Where(s => s.Code == viewModel.Code).FirstOrDefault<Stock>();

        if(existingStock == null)
        {
           Stock stock = new Stock(viewModel);
           db.Stocks.Add(stock);
        }
        else
        {
           existingStock.UpdateStock(viewModel);
           db.Entry(existingStock).State = EntityState.Modified;
        }
        db.SaveChanges();

        return PartialView("StockListPartialView", db.Stocks.Include("Description").ToList());
     }
  }

这个例外:

发生了参照完整性约束违规:属性 定义引用约束的值不一致 关系中的主体对象和依赖对象之间的关系。

在我设置要修改的条目状态时发生。到目前为止我发现的解决方法是设置existingStock.Description = null,但描述不再更新。

编辑 两个类中的Code 属性

【问题讨论】:

  • 您使用哪个属性将StockDescriptionStock 关联起来?只有DescriptionStock 上,还是在StockDescription 中的某个地方有StockId 属性?
  • UpdateStock 是做什么的?它是否正确设置了 FK?
  • StockDescription 和 Stock 与 Code 属性相关。并且示例代码中给出了 UpdateStock,不,它不会更改 FK。
  • 如果它们是通过Code 关联的,那么这个属性似乎与Stock 和它的StockDescription 不同。
  • 这是我想的,但调试器告诉我相反,它们实际上是相同的(不是相同的实例,而是相同的值)

标签: c# asp.net entity-framework


【解决方案1】:

如果您有一个现有的Stock,您必须明确替换它的StockDescription。为此,您需要对代码进行两处更改:

var existingStock = db.Stocks
                      .Include(s => s.StockDescription) // <= added
                      .Where(s => s.Code == viewModel.Code)
                      .FirstOrDefault<Stock>();

if(existingStock == null)
{
    Stock stock = new Stock(viewModel);
    db.Stocks.Add(stock);
}
else
{
    // Line added:
    db.Entry(existingStock.StockDescription).State = EntityState.Deleted;

    existingStock.UpdateStock(viewModel);
    // Not necessary:
    // db.Entry(existingStock).State = EntityState.Modified;
}
db.SaveChanges();

所以你必须Include 现有的StockDescription。 (它不是通过延迟加载加载的,因为它不是virtual 属性。)并且您已将其状态设置为已删除。现在 EF 知道它应该删除旧的描述并添加一个新的。

【讨论】:

  • 谢谢,我会测试它,但我不想删除描述,只需更新它,因为其他 Stock 对象可能具有相同的 StockDescription
  • 我不确定这是一个 1:n 关联(根据您的编辑)。例外使用“主要和从属”,这是 1:1 的术语。你有流畅的映射吗?
  • 但也许使用Include 而不是EntityState.Deleted 就足够了。
猜你喜欢
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 2017-10-04
  • 2019-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多