WCF RIA Changeset Submit Order. Why is it inserting child entity before parent entity? - entity-framework-4.1

Here's my problem : I'am using Silverlight+ WCF RIA + EntityFramework and domain datasource. I'am inserting on the client side a parent entity and then a child entity (a parent can have many children) like this :
Parent p = new Parent();
p.PropertyA = "MyTest";
if (!this.domainContext.Parents.Contains<Parent>(p))
this.domainContext.Parents.Add(p);
Child c = new Child();
c.PropertyOfC = "Togodo";
if (!this.domainContext.Childs.Contains<Child>(c))
this.domainContext.Childs.Add(c);
c.parent = p;
p.Child.Add(c);
// Submit update RAISE ERROR
domainContext.SubmitChanges(submitOp =>
{
// Declare error
Exception error = null;
// Set error or result
if (submitOp.HasError)
{
error = submitOp.Error;
}
// Invoke completion callback
if (completed != null)
completed(error);
}, null);
}
When I call the "submitChanges", on the serveur side, the "insert method" of the child enity is called before the parent one. So an exception occurs due to foreign key constraint.
The code here is simplified. On the real case, I can't call submit changes twice (one after created the Parent Entity, and one after the child creation)
How can I control the insert order on server side, or what I'am doing wrong ?
Thanks for any help.

Thanks for your help but I found the problem.
In fact I was inserting the parent entity through stored procedure and I haven't correctly configure the "output result binding" of the Id. So the parent Id was not correctly updated on my entity model after insertion on the database.

Related

Why is persist in JPA clearing the existing data in the table row?

I am trying to update data to a mySQL database using JPA. I have no problem persisting data but flush will not work as expected. I retrieve the id for the login session, set that id (it is the primary key) along with setting the description field that I want merged to the database. I have debugged line by line through this method and all variables contain the expected values. Any ideas or suggestions to overcome this problem are appreciated.
public String update() {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();
if(true){
em.getTransaction().begin();
String sessionEmail=Util.getEmail();
//Create query to find user passwords matching the inputted name
Query myQuery = em.createQuery("SELECT u FROM BusinessAccount u WHERE u.email=:email");
myQuery.setParameter("email", sessionEmail);
List<BusinessAccount> accounts=myQuery.getResultList();
int intId=accounts.get(0).getId();
businessAccount.setId(intId);
String des=businessAccount.getDescription();
businessAccount.setDescription(des);
em.flush();
addMessage(new FacesMessage(FacesMessage.SEVERITY_INFO,
"User Registration Successful!", null));
return "success";
}
else {
addMessage(new FacesMessage(FacesMessage.SEVERITY_ERROR,
"User Registration Failed!", null));
return "failure";
}
}
merge() persists all the state of the entity. Not just the non-null fields. I it wasn't, you would complain that you want to set some field to null and that merge() ignores it and leaves it as is.
So get an entity from the database, and modify it, instead of only gettings its ID, creating a new entity instance from scratch and only settings some of its fields.
Note that, if you get the entity and modify it inside a single transaction, you don't even have to call merge(): the new state will be made persistent automatically.

Getting identity column value using entity framework 4.1

I'm using entity framework 4.1 (VS 2010, SQL Server 2012) for inserting data into a database.
First I create an instance of an object, fill the properties with values and call AddObject(), like this:
VideoData videodata = new VideoData();
videodata.StartCaptureTime = startCaptureTime;
videodata.EndCaptureTime = endCaptureTime;
videodata.CameraID = CameraID;
using (var context = new PercEntities())
{
if (context.VideoDatas.Where(c => c.VideoID == videoID).Count() == 0)
{
var videoData = new VideoData
{
StartCaptureTime = startCaptureTime,
EndCaptureTime = endCaptureTime,
CameraID = CameraID,
};
context.VideoDatas.AddObject(videoData);
context.SaveChanges();
}
}
The thing is, that the table in the database has an identity column:
VideoID int IDENTITY(1,1)
and I need to get the value inserted by the identity function in order to fill additional objects, that have the VideoID as a foreign key. for example:
FrameData frameData = new FrameData();
frameData.VideoID = videodata.VideoID;
frameData.Path = path;
The only thing I could think of was to query for the max identity right after AddObject(videoData), but I'm afraid of race conditions.
I'm new to Entity Framework, so I'd be happy for any guidance on this.
If you have other objects which require VideoID as FK you just need to correctly configure your navigation properties between VideoData and those other types and EF will handle it for you.
Call to AddObject does not insert your data to database and because of that you cannot get the identity value after this call. Only call to SaveChanges will push all your changes to database and during this call EF will handle referential integrity internally (but only if you have your model correctly configured with relations).
After calling SaveChanges your VideoID should be populated automatically if you have everything correctly configured.

Cannot add an identity that already exists

I'm using C#4.0 in a simple expense recording app. I'm trying to save to a table with an auto incremented id field, set as the primary key. It works fine the first time I use it, but the second and subsequent time, I get the "Cannot add an identity that already exists" error.
Here's the code I'm having trouble with
public bool SaveClaim(Claim newClaim, bool blNew)
{
bool blSuccess = true;
try
{
expContext.Claims.InsertOnSubmit(newClaim);
expContext.SubmitChanges();
claim = null;
}
catch (Exception e)
{
blSuccess = false;
MessageBox.Show(e.ToString());
}
return blSuccess;
}
I've been working on this all morning, and it's driving me daft. I'd be glad for any help.
Ensure you have the following properties set in your dbml for the identity column of Claim:
Auto Generated Value = true
Auto-Sync = OnInsert
Also ensure that your new Claim object is actually a new object, and not a reuse of the one you previously added.
Maybe you should try updating your designer.
Remove the table Claim, update the server explorer, and add it again.
At least that's what I do when I get this error. It usually shows when I set the identity column on the database after compiling.
Maybe you are trying to UPDATE newClaim using the INSERT method.
If newClaim has an ID and the method expContext.Claims.InsertOnSubmit(newClaim) is trying to insert a record with that ID. That could be the issue.
if (blNew)
expContext.Claims.InsertOnSubmit(newClaim);
else
expContext.Claims.UpdateOnSubmit(newClaim); //-- Assumed method
Additional
Here is a useful thread: MSDN Forums
if (blNew)
{
expContext.Claims.InsertOnSubmit(newClaim);
}

handle transaction in Linq to sql

I am implementing the asp.net MVC web application, where i am using the Linq to Sql to manipulate the data in database. but in my one of action, i want to insert multiple table entries which are depends upon each other by referring previous insertion Id's. So i just wnat to know how to handle the transaction, like begin transaction, commit,rollback and all like in ADO.net. how to manage this. what if one of insertion get crashed in the middle of manipulation?
Note:- I am not using the Stored procedures here. I am using Lambda expressions and methods. Also these are use in different manager classes.
Example:
For Create Subject - used method in SubjectManager class to insert subject infor, that returns subject Id. within this subjectid i am inserting the let say its chapters with another method in manager class as ChapterManager. which again returns the ChapterId, on base of this chapeter Id , inserting the Topics of chapter. that again uses Topic manager same like above.in each manger class i am creating dataContext object for the same. and I am controlling all this within a single action in my controller. but worrying about the transaction management. how I can use here ?
The DataContext already includes an embedded transaction object. For example, let's say you are placing a new order for a customer. You can set up your model so that the following code updates both the Customer AND Order table with a single SubmitChanges. As long as a foreign key relationship exists between the two tables, the embedded transaction object handles both the Customer update and the Order insert in the same transaction. Using a TransactionScope object to encase a single DataContext is redundant:
using (DataContext dc = new DataContext())
{
Order order = new Order();
order.ProductID = 283564;
order.Quantity = 7;
order.OrderDate = DateTime.Now;
Customer customer = dc.Customers.Single(c => c.CustomerID == 6);
customer.LastUpdate = order.OrderDate;
customer.Orders.Add(order);
dc.SubmitChanges();
}
using(TransactionScope scope = new TransactionScope())
{
using(DataContext ctx = new MyDataContext())
{
ctx.Subject.Add(subject);
Chapter chapter = new Chapter();
chapter.SubjectId = subject.Id;
ctx.SubmitChanges();
ctx.Chapter.Add(chapter);
ctx.SubmitChanges();
scope.Complete() // if it all worked out
}
}
From the System.Transactions namespace I believe.

"An attempt has been made to Attach or Add an entity that is not new..." after calling ObjectChangeConflict.Resolve()

I have a pair of classes which, when updated together as shown below are guaranteed to cause a ChangeConflictException because a trigger on child object table updates a value on the parent object record. I believe I am following the correct procedure for resolving the conflict and resubmitting the update, but upon calling the second db.SubmitChanges (or even if I call db.GetChangeSet()), I get the "an attempt has been made to attach or add an entity that is not new blah blah blah" error.
using (SurveyDB db = new SurveyDB())
{
Parent p = db.Parents.Single(t => t.Id == 1);
p.Children.Add(new Child {...});
p.SomeProperty = "new value";
try
{
db.SubmitChanges();
}
catch (ChangeConflictException e)
{
foreach (ObjectChangeConflict o in db.ChangeConflicts)
o.Resolve(RefreshMode.KeepChanges, true);
db.SubmitChanges(ConflictMode.FailOnFirstConflict);
}
}
Any help greatly appreciated.
The resolution for me was to set dbml "Update Check" property for the fields set by the trigger to "Never" - this works for the situation where the application never modifies those fields. Otherwise, I'd have had to call SubmitChanges twice - once after editing the parent object and then again after adding the child object (followed by retrieving the parent-object again).