Reputation: 459
I have a complex graph with a collection child entities.The relationship between parent and child entities is one-many relationship and has an Independent association. I know that I cant persist my graph without manual synchronization which I want to avoid. I found GraphDiff solution promising and I started exploring it but I couldn't achieve what I intend to as my scenario is somewhat peculiar. This issue is purely related to GraphDiff but I also welcome other solutions.
public class person
{
public virtual int Id {get; set;} //primary key
public virtual string Name {get; set;}
public virtual ICollection<Car> Cars {get; set;}
}
public class Car
{
public virtual int PersonId {get; set;} // is a foreign key
public virtual Datetime BoughtDate {get; set;} // this property and above mentioned foreign key together makes a primary key in database
public virtual DateTime InsuraceStartDate {get; set;}
public virtual DateTime InsuraceExpiryDate {get; set;}
public virtual DateTime LastServiceDate {get; set;}
}
At any given time my Person.Cars collection may have 1. A new car object. 2. An existing car object with updated values.(insurance or service dates).
Id property on Person and PersonId on Car will be 0.
Person _person = GetPersonToAddOrUpDate();
int id = _person.id; //id will be 0.
At this point we are not sure the object we received has to added or updated. PersonId on child entities(Cars) will also be 0.Now if we call.
Context.UpdateGraph(_person, m => m.OwnedCollection(x => x.Cars));
throws exception at FindEntityMatching(entity).
To overcome this I have to update Id property on person.
var dbPersonId = Context.Single<Person>(x => x.Name == _person.Name).Id;
_person.id = dbPersonId != null ? dbPersonId : 0;
Context.UpdateGraph(_person, m => m.OwnedCollection(x => x.Cars));
It deletes all entities in dbPerson.Cars and adds _person.Cars to dbPerson.Cars and saves. It means all records in my Cars table in database are deleted and records from _person.Cars are inserted. I noticed this is happening because Now the child entities does not have a Id property. I have to set them manually.
foreach(var car in _person.Cars)
car.PersonId = _person.Id
Now if you call
Context.UpdateGraph(_person, m => m.OwnedCollection(x => x.Cars));
This will add entities in collection from transient object missing in the persistent object and updates the object matching in the persistent object and deletes rest of the entities from the persistent object.
var dbCars = conext.Where(x => x.Personid == _person.Id).Select(x).ToList();
say dbCars.Count is 8 and _person.Cars.Count is 3.(one new car and 2 old cars with updated values) Once you run.
Context.UpdateGraph(_person, m => m.OwnedCollection(x => x.Cars));
2 old cars from _person.Cars matching in dbCars will be updated. 1 new car from _person.Cars not matching in dbCars will be added.
Now the count of dbCars must be 9 as we added a new car. Now check the count.
var dbCarCount = conext.Where(x => x.Personid == _person.Id).Select(x).ToList().Count();
dbCarCount will be 3. Rest of the 6 cars from dbCars are being removed.
I wish I am wrong as I like to use your solution.My work in this area is stalled. Please let me know If I'm missing something or you need more information. I know my write up is confusing as I tried to put all my testing experience with GraphDiff. Hope you address this issue.
Upvotes: 2
Views: 3430
Reputation: 104751
There are two tools I've found for that:
Upvotes: 0
Reputation: 22595
If you have a disconnected graph and you want to merge it to the database then there are 3 things it should do:
You appear to be having an issue with the last part.
If the graph has not been retrieved from the database in the first place then you are not using GraphDiff as it was intended. You will have to do your adding and updating manually.
Upvotes: 2