如何解决INSERT上的实体框架主键冲突?

时间:2014-02-16 14:54:29

标签: .net entity-framework primary-key

我尝试过几件事:

  1. 将数据附加到上下文
  2. 手动修改edmx文件(此处为source
  3. 手动获取ForeignKey对象(data.RTMS_GsmOperator = Context.RTMS_GsmOperator.FirstOrDefault(c => c.Id == data.GsmOperatorId);)然后保存SaveChanges
  4. 以下是选项1的代码:

         data.Id = GetMaxId(data)
         Context.Attach(data); //Here I attached it
         Context.RTMS_PackageApplication.AddObject(data);
         Context.SaveChanges(); //I get the error here
    

    以下是选项3的代码:

    data.Id = GetMaxId(data)

     data.RTMS_GsmOperator = Context.RTMS_GsmOperator.FirstOrDefault(c => c.Id == data.GsmOperatorId); //Here
     data.RTMS_Machine = Context.RTMS_Machine.FirstOrDefault(c => c.Id == data.MachineId); //Here
    
     Context.RTMS_PackageApplication.AddObject(data);
     Context.SaveChanges(); //I get the error here
    

    以上都没有工作!

    enter image description here

    注意:Id的NONE是自动增量的。

    当我运行以下代码时:

    public RTMS_PackageApplication Insert(RTMS_PackageApplication data)
    {
         using (var Context = base.RtmsEntites)
         {
             //Since, its not auto-incremental, I do it manually.
             data.Id = GetMaxId(data)
             Context.RTMS_PackageApplication.AddObject(data);
             Context.SaveChanges(); //I get the error here
         }
    }
    

    错误:

    Violation of PRIMARY KEY constraint 'PK_GsmOperator'. Cannot insert duplicate key in object 'dbo.RTMS_GsmOperator'. The duplicate key value is (1).
    The statement has been terminated.
    

    如果你必须知道这里是GetMaxId方法:

    private int GetMaxId(RTMS_PackageApplication data)
    {
    int Result = 1;
    var Temp =
                            base.RtmsEntites.RTMS_PackageApplication.AsQueryable().OrderByDescending(u => u.Id).
                                FirstOrDefault();
                        if (Temp != null)
                            Result = Temp.Id + 1;
    
    return Result;
    }
    

    至于自动增量;问题出现在GsmOperatorId(外键数据表)上,那里的数据已经是ALREADY,我只想将Id添加到PackageApplciation表中。所以,我尝试仅添加新的GsmOperator PackageApplication

    EF正在尝试插入GsmOperator和Machine实体。但为什么?我甚至在下面的一个答案中重新附上了它。

    我该如何解决这个问题?

3 个答案:

答案 0 :(得分:2)

您是否可以尝试使用用于加载RTMS_GsmOperator的相同DataContext实例来保存更改?像这样:

var opr = theContext.RTMS_GsmOperator.FirstOrDefault(c => c.Id == WHATEVER); 
var pa = new RTMS_PackageApplication(); 
pa.RTMS_GsmOperator = opr; 
pa.RTMS_Machine= <RTMS_Machine_Variable> ; 
opr.RTMS_PackageApplications.Add(pa); 
theContext.SaveChanges();

答案 1 :(得分:0)

我认为这里适当的解决方案是使字段成为自动增量id字段,而不是试图自己捏造它。

即使您可以设法通过此错误,当负载增加并且多个客户端同时插入记录时会发生什么? - 你很可能会遇到冲突,即两个不同的客户端都被告知下一个'maxId'是相同的数字......让DB服务器为你处理这个...这就是它擅长的。

答案 2 :(得分:0)

好的,我发现我犯了一个小错误,感谢Elio.Batista我意识到了。

出于验证目的,我将一些默认值设置为某些属性。在这些属性中,有GsmOperatorMachine

但是,我错误地将GsmOperatorId属性设置为RTMS_GsmOperator实体,而不是设置E-F属性。因为我设置了一些默认值,它不为空,E-F将其识别为实体并尝试INSERT

因此,在EF INSERT期间,对象ForeignKey链接实体应为null。

我的错误代码:

//Notice that this is partial entity class of EF edmx file
public partial class RTMS_PackageApplication
{
    public RTMS_PackageApplication()
    {
       this.RTMS_GsmOperator = new RTMS_GsmOperator();
       this.RTMS_Machine = new RTMS_Machine();
    }
}

现在,我改变并更正为:

//Notice that this is partial entity class of EF edmx file
public partial class RTMS_PackageApplication
{
    public RTMS_PackageApplication()
    {
        this.GsmOperatorId = 0; //As Default value
        this.MachineId =  0; //As Default value
    }
}