【问题标题】:SaveChanges() is saving Unchanged recordsSaveChanges() 正在保存未更改的记录
【发布时间】:2017-09-15 01:48:58
【问题描述】:

我不知道我是否遗漏了什么......无论如何:

例如,您可以看到,属性为“HomeTeam”=“Forest Green Rovers”的对象的状态为“Unchanged”。无论如何,就我而言,所有实体都是“不变的”。所以,如果我是正确的,saveChanges 不应该尝试将它们插入到我的表中,但这就是它正在发生的事情:

主键已被违反,但 EF 不应该尝试添加此记录(属性 HomeTeam = 'Forest Green Rovers' 的记录),因为它是“未更改”,对吧?

EF 为什么要这样做?

实体:

{
using System;
using System.Collections.Generic;

public partial class MatchInfo
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public MatchInfo()
    {
        this.Sport = "Soccer";
        this.OddsInfoes1X2 = new HashSet<OddsInfo1X2>();
        this.Odds1X2Movements = new HashSet<OddsMovement>();
        this.OddsInfoOverUnders = new HashSet<OddsInfoOverUnder>();
        this.OddsMovementOverUnders = new HashSet<OddsMovementOverUnder>();
        this.HistoryResults = new HashSet<HistoryResult>();
    }

    public string League { get; set; }
    public System.DateTime Date { get; set; }
    public string HomeTeam { get; set; }
    public string AwayTeam { get; set; }
    public string FinalScore { get; set; }
    public string Sport { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<OddsInfo1X2> OddsInfoes1X2 { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<OddsMovement> Odds1X2Movements { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<OddsInfoOverUnder> OddsInfoOverUnders { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<OddsMovementOverUnder> OddsMovementOverUnders { get; set; }
    public virtual TeamsStatFinal TeamsStatFinal { get; set; }
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<HistoryResult> HistoryResults { get; set; }
}

}

更多信息:

foreach (something){
     /*iterating on a web page and where I build the object oMatchInfo */
     if (oMatchInfo != null)
     {
          oMatchInfoTemp = (from m in context.MatchInfoes where m.HomeTeam == oMatchInfo.HomeTeam && m.AwayTeam == oMatchInfo.AwayTeam && m.Date == oMatchInfo.Date select m).FirstOrDefault<MatchInfo>();
          if (oMatchInfoTemp == null)
          {
              context.MatchInfoes.Add(oMatchInfo);
          }
          else
          {                                         
              context.OddsInfoes1X2.AddRange(oMatchInfo.OddsInfoes1X2);
          }
     }

}
/* here there is the context.saveChanges() - the context is the same */

操作。我发现了我的错误,这真的很愚蠢:-( 在 for 内部的相关函数中有一些未注释的代码,我在其中添加实体而不检查 PK 约束。 状态“未改变”(第一张图片)让我感到困惑,我一直专注于... 对不起:-)

【问题讨论】:

  • 是所有代码吗?你能把这个类也包括在实体中吗
  • 请添加另一个定义密钥的partial class MatchInfo。您的问题是该部分中的Edit: That's the part where I check the primary key before adding in the context:,请添加调用位置。
  • 就像我说的添加!你在哪里打电话if (oMatchInfo != null) {代码....

标签: c# entity-framework


【解决方案1】:

如果您想将实体添加到不是新实体(数据库中已经存在PK)的上下文中,那么您需要附加实体而不是添加它。

更多详情在这里https://msdn.microsoft.com/en-us/library/jj592676(v=vs.113).aspx

要详细说明,请仔细查看上下文内容。您将找到一个具有已添加状态的实体。

【讨论】:

  • 我认为这不能解决问题。他不想补充。他遍历现有记录。他将按原样离开那里,即它们不是新的或添加的状态。 NvM!!!!!! he added more code!
  • @Seabizkit 我们会看到的。这里有一个复合 PK,可能会使问题复杂化。
  • 他在事后添加了您的评论所依据的相关代码..所以您的回答更有意义,但只有在他添加了重要位之后
  • @Seabizkit 是的,我对根本问题进行了猛烈抨击,因为它似乎太熟悉了
【解决方案2】:

您正在向数据库中添加一个现有条目。

if (oMatchInfo != null)
{
    oMatchInfoTemp = (from m in context.MatchInfoes where m.HomeTeam == 
    oMatchInfo.HomeTeam && m.AwayTeam == oMatchInfo.AwayTeam && m.Date == 
    oMatchInfo.Date select m).FirstOrDefault<MatchInfo>();

    if (oMatchInfoTemp == null)
    {
        context.MatchInfoes.Add(oMatchInfo);
    }
    else
    {                                         
        context.OddsInfoes1X2.AddRange(oMatchInfo.OddsInfoes1X2);
    }
}

这样,您添加的模型的 ID 与数据库中的条目匹配,因此您的数据库给出了 cannot insert duplicate key 错误。

【讨论】:

    【解决方案3】:

    我认为问题出在这里:

    if (oMatchInfo != null)
    {
         oMatchInfoTemp = (from m in context.MatchInfoes where m.HomeTeam == oMatchInfo.HomeTeam && m.AwayTeam == oMatchInfo.AwayTeam && m.Date == oMatchInfo.Date select m).FirstOrDefault<MatchInfo>();
         if (oMatchInfoTemp == null)
         {
             context.MatchInfoes.Add(oMatchInfo);
         }
         else
         {
             // CODE SMELL                                         
             context.OddsInfoes1X2.AddRange(oMatchInfo.OddsInfoes1X2);
         }
     }
    

    在其他情况下,您将重新添加许多已插入数据库的实体,这就是重新链接您当前的匹配以进行插入。

    也许您想插入现有 X2 和新 X2 之间的差异。典型代码如下所示:

    context.OddsInfoes1X2.AddRange(oMatchInfo.OddsInfoes1X2.Where(t => !oMatchInfoTemp.OddsInfoes1X2.Contains(t)))
    

    你想在 else 语句中做什么?

    希望对您有所帮助!

    【讨论】:

    • 同意,这个 if 块需要证明
    • 我正在调查该代码,但如果我评论上述行,我仍然会得到同样的错误(我的意思是 else 语句)。无论如何,我正在尝试在数据库中添加与第一个相关的另一个实体。
    • 谁在创建 oMatchInfo 变量?
    【解决方案4】:

    仍然无法从您的代码中看出,因为您的显示不够。

    您需要包含更多代码,以便我们了解您为何如此称呼自己。

    我希望这段代码能帮助你理解,这不是你的解决方案,我只是想表明你的 for-each 看起来不正确,这取决于你在什么时候做什么,但因为你不是显示所有我们无法分辨的代码。

      public void Save(TEntity entity) //change this to your entity
        {
            if(entity == null)
                return;
    
            //change this to your key, this is the identifier for new
            if (entity.Id == 0) 
            {
                entity.CreateOnDateTime = DateTime.Now;
                Context.Set<TEntity>().Add(entity);
            }
    
    
            Context.SaveChanges(); //this may not suit your design
        }
    

    【讨论】:

    • 这可以解决您的问题,但与导致问题的做法相去甚远。以后再回过头来看看这个错误,更清楚地再次检查代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多