2

I've tried few things:

  1. Attaching data into Context
  2. Manually modifying edmx file (here is the source)
  3. Manually getting the ForeignKey Object by (data.RTMS_GsmOperator = Context.RTMS_GsmOperator.FirstOrDefault(c => c.Id == data.GsmOperatorId);) and then SaveChanges

Here is the code for the Option 1:

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

Here is the code for the Option 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

None above worked!

enter image description here

NOTE: NONE of the Id's are auto-incremental.

When I run the code below:

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
     }
}

Error:

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.

If you must know here is the GetMaxId method:

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;
}

As for the auto-incremental; the problem is on the GsmOperatorId (Foreign Key data table) and the data is ALREADY there, I just want to add the Id into PackageApplciation Table. So, I'm NOT trying to add new GsmOperator only PackageApplication

The EF is trying to INSERT GsmOperator and Machine entities as well. But why? I even re-attached it as in one of the answeres below.

How can I fix this?

Community
  • 1
  • 1
E-A
  • 1,995
  • 6
  • 33
  • 47
  • Option 1 or 3 should be successful. Can you show the complete code how you tried the two solutions? – Slauma Feb 16 '14 at 15:10
  • I added the code into my question. – E-A Feb 16 '14 at 15:31
  • How do you manage the lifetime of the `base.RtmsEntites` context? Apparently you don't create a new one in the `using` block but use the existing one. (That `using` statement is *very* strange.) For some reason the object `data.RTMS_GsmOperator` is in state `Added` and this might have happened much earlier if you have a context with long lifetime. – Slauma Feb 16 '14 at 16:14
  • 'base.RtmsEntities' is always new(). Ex: 'new RTMSEntities(Utility.ConnectionStrings.RtmsEntities)' The only reason I did that to reduce the code and more managable just incase later on I need something more, I added into a property which always returns as NEW – E-A Feb 16 '14 at 16:17
  • I suggest that you add the lines `ObjectStateEntry entry; bool inContext = Context.ObjectStateManager.TryGetObjectStateEntry(data.RTMS_GsmOperator, out entry);` into your `using` block at several places to check if the `RTMS_GsmOperator` is in the context and in which state `entry.State` and when the state changes to `Added`. – Slauma Feb 16 '14 at 16:34
  • right before Context.RTMS_PackageApplication.AddObject(data); the inContext value returns FALSE. Right AFTER Context.RTMS_PackageApplication.AddObject(data); it returns TRUE – E-A Feb 16 '14 at 16:40
  • Include the `Context.Attach(data)` from your option 1. (It's clear that the Gsm... will be inserted without the Attach-line.) And also monitor `entry.State`. – Slauma Feb 16 '14 at 16:47

3 Answers3

2

Can you try to Save the changes using the same DataContext instance that you use to to load RTMS_GsmOperator ? Something like this:

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();
E-Bat
  • 4,792
  • 1
  • 33
  • 58
  • A very sound approach. But WTH is wrong with EF? I event DETACHED the Gsm and the Machine first then re-attached it, still not working.. And also tried JUST attaching those 2 entities without detaching as well. Still no good. – E-A Feb 16 '14 at 16:12
  • As i can see you are loading those instances in one Context and using it in another different Context instance. What base.RtmsEntites looks like? – E-Bat Feb 16 '14 at 16:19
  • Its actually NOT a previously created instance. 'base.RtmsEntities' is always new(). Ex: 'new RTMSEntities(Utility.ConnectionStrings.RtmsEntities)' The only reason I did that to reduce the code and more managable just incase later on I need something more, I added into a property which always returns as NEW – E-A Feb 16 '14 at 16:23
  • Please, post the relevant definition for RTMS_GsmOperator and its mapping? – E-Bat Feb 16 '14 at 16:37
  • Isnt it what you want that I posted the image on my question? – E-A Feb 16 '14 at 17:08
  • Forget my last comment because you are using edmx. Can you try to Save the changes using the same DataContext instance that you use to to load RTMS_GsmOperator ? Something like this: `var opr = theContext.RTMS_GsmOperator.FirstOrDefault(c => c.Id == WHATEVER); VAR pa = new RTMS_PackageApplicatio(); pa.RTMS_GsmOperator = opr; pa.RTMS_Machine= ; opr.Add(pa); theContext.SaveChanges();` – E-Bat Feb 16 '14 at 17:31
  • Thank you Elio, you help me realize something. I'll be posting my answer. – E-A Feb 16 '14 at 20:19
0

I think the proper solution here is to make the field an autoincrement id field, instead of trying to fudge it yourself.

Even if you can manage to get past this error, what happens when load increases and multiple clients are inserting records at the same time? - you may very well get conflicts, i.e. two different clients both get told that the next 'maxId' is the same number...Let the DB server handle this for you...that's what its good at.

E.J. Brennan
  • 45,870
  • 7
  • 88
  • 116
  • THe problem is on the GsmOperatorId and the data is ALREADY there, I just want to add the Id into PackageApplciation Table. So, I'm NOT trying to add new GsmOperator only PackageApplication – E-A Feb 16 '14 at 15:25
  • And for the record: I did try to make PackageApplication auto-incremental, and updated my model on .net side, but did not worked. Still same error! – E-A Feb 16 '14 at 15:54
0

Ok, I found out that I made a small mistake and thanks to Elio.Batista I realized it.

For validation purposes I set some default values to some properties. Among these properties there are GsmOperator and Machine.

But, instead of setting the GsmOperatorId property, I mistakenly set the RTMS_GsmOperator property which is the E-F entity. And because I set some default value, its not null and E-F recognizes it as a NEW entity and tries to INSERT it.

So, during an EF INSERT, the objects ForeignKey linked entity should be null.

My wrong code:

//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();
    }
}

Now, I changed and corrected to:

//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
    }
}
Community
  • 1
  • 1
E-A
  • 1,995
  • 6
  • 33
  • 47