.net 如何解决插入时实体框架主键冲突?

.net 如何解决插入时实体框架主键冲突?,.net,entity-framework,primary-key,.net,Entity Framework,Primary Key,我尝试了几件事: 将数据附加到上下文中 手动修改edmx文件(以下是示例) 通过(data.RTMS\u GsmOperator=Context.RTMS\u GsmOperator.FirstOrDefault(c=>c.Id==data.GsmOperatorId);手动获取ForeignKey对象,然后保存更改 以下是选项1的代码: data.Id = GetMaxId(data) Context.Attach(data); //Here I attached it

我尝试了几件事:

  • 将数据附加到上下文中
  • 手动修改edmx文件(以下是示例)
  • 通过(
    data.RTMS\u GsmOperator=Context.RTMS\u GsmOperator.FirstOrDefault(c=>c.Id==data.GsmOperatorId);
    手动获取ForeignKey对象,然后保存更改
  • 以下是选项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(数据)

    以上都没用

    注意:没有一个Id是自动递增的。

    当我运行下面的代码时:

    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
    (外键数据表)上,并且数据已经存在,我只想将Id添加到
    packageapplication
    表中。因此,我不是在尝试添加新的
    GsmOperator
    PackageApplication

    EF正在尝试插入GsmOperator和机器实体。但是为什么呢?我甚至在下面的回答中重新附上了它


    如何修复此问题?

    我认为正确的解决方案是将该字段设置为自动增量id字段,而不是试图自己伪造它


    即使您能够设法克服此错误,但当负载增加且多个客户端同时插入记录时会发生什么情况您很可能会遇到冲突,即两个不同的客户端都被告知下一个“maxId”是相同的数字…让DB服务器为您处理这个问题…这就是它的优点。

    您是否可以尝试使用用于加载RTMS\u 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();
    
    var opr=context.RTMS\u GsmOperator.first或default(c=>c.Id==WHATEVER);
    var pa=新的RTMS_PackageApplication();
    pa.RTMS_GsmOperator=opr;
    pa.RTMS_机器=;
    操作RTMS_PackageApplications.Add(pa);
    context.SaveChanges();
    
    好的,我发现我犯了一个小错误,多亏了我意识到了这一点

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

    但是,我没有设置
    GsmOperatorId
    属性,而是错误地设置了
    RTMS\u GsmOperator
    属性,即
    E-F
    实体。因为我设置了一些默认值,所以它不为null,
    E-F
    将它识别为一个新的实体,并尝试
    插入它

    因此,在
    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
        }
    }
    

    选择1或3应该是成功的。您能展示完整的代码吗?您是如何尝试这两种解决方案的?我在问题中添加了代码。您如何管理
    base.RtmsEntites
    上下文的生存期?显然,您没有使用
    块在
    中创建新的,而是使用现有的。(使用
    语句的
    非常奇怪。)由于某种原因,对象
    data.RTMS\u GsmOperator
    处于状态
    Added
    ,如果您的上下文具有较长的生存期,“base.RtmsEntities”总是新的()。例如:“new RTMSEntities(Utility.ConnectionStrings.RTMSEntities)”我这样做的唯一原因是为了减少代码和提高可管理性,以防以后我需要更多的东西,我添加到一个总是以new形式返回的属性中,我建议您添加行
    ObjectStateEntry;bool inContext=Context.ObjectStateManager.TryGetObjectStateEntry(data.RTMS\u GsmOperator,out条目)
    块在多个位置检查
    RTMS\u GsmOperator
    是否在上下文中,并且处于哪个状态
    条目中。状态
    以及当状态更改为
    添加
    时。问题在于GsmOperatorId上,数据已经存在,我只想将Id添加到PackageAppLocation表中。所以,我并没有试图添加新的仅GsmOperator的PackageApplication,我确实尝试使PackageApplication自动递增,并在.net端更新了我的模型,但没有成功。还是一样的错误!非常合理的方法。但是EF有什么问题吗?我先断开Gsm和机器,然后重新连接,但仍然无法工作。。还尝试了只附加这两个实体而不分离。还是不行。正如我看到的,您正在一个上下文中加载这些实例,并在另一个不同的上下文实例中使用它。base.RtmsEntites看起来像什么?它实际上不是以前创建的实例。”base.RtmsEntities'始终是新的()。例如:“new RTMSEntities(Utility.ConnectionStrings.RTMSEntities)”我这样做的唯一原因是为了减少代码和提高可管理性,以防以后我需要更多的东西,我添加到一个总是以NEWPlease返回的属性中,发布RTMS\u GsmOperator的相关定义及其映射?我在我的问题上发布的图像不是你想要的吗?
    //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
        }
    }