| Author |
Share Topic Topic Search Topic Options
|
smi-mark
DevForce MVP
Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
|
Post Options
Quote Reply
Topic: Possible Bug - Import entities Posted: 26-May-2011 at 3:14pm |
|
Hi Denis,
Thanks for the update. I'm not sure if my workaround works in all cases, but I will retest it again when I get chance.
The only problem with AcceptChanges(), is that now they are unmodified, so a call to SaveChanges() won't pick those entities up will it?
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 26-May-2011 at 3:12pm |
Hi Mark;
Sorry it took so long to get back. Since you've already found a workaround, this has probably become a non issue for you.
Anyway, I just want to follow up what I found. It may or may not be useful.
The sample you sent does indicate that calling .SetModified() doesn't work. But the strange thing is that, when the EntityState is first Added, then SetModified(), the ImportEntities works. It will update the temp id from -100 to -101 and update the original CustomerAddress. However, when I modify the address again, ImportEntities stops working, i.e. it will keep the -101 CustomerAddress and create a new -102 CustomerAddress. What's even stranger is that I can't repro it outside the solution.
If I modify the code slightly to the following, using AcceptChanges(), then ImportEntities will keep the original temp id and not create duplicate CustomerAddress.
vm.EntityManager .FindEntities(EntityState.Added | EntityState.Modified) //.FindEntities(EntityState.Added) .OfType<Entity>() .ForEach(entity => entity.EntityAspect.AcceptChanges()); //.ForEach(entity => entity.EntityAspect.SetModified());
var entities = vm.EntityManager //.FindEntities(EntityState.AnyAddedModifiedOrDeleted) .FindEntities(EntityState.AllButDetached) .OfType<Entity>(); _primaryEntityManager.ImportEntities(entities, MergeStrategy.OverwriteChanges);
|
I'll continue to investigate this and provide updates when I've found something useful. But, again, as you've found a workaround, I think this issue can be considered closed.
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 16-May-2011 at 12:02pm |
|
Thank you Mark. Appreciate the help. I'll get back in touch once I take a look at the sample.
|
 |
smi-mark
DevForce MVP
Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
|
Post Options
Quote Reply
Posted: 16-May-2011 at 11:38am |
|
Hi Derick,
I have prepared a sample. I have put the zip on our webserver:
http://71.164.192.3/ImportSL.zip
I have not used any frameworks with this sample, so it's not all best practices!
You will see two 'screens'
the top is the customer screen that lets you add/edit an address, when you click one of these buttons you will be able to update the address screen.
If you edit the address and save it, then save and edit again, you will see it starts duplicating the data. You will see it is not merging it in properly.
If you have any questions on it please let me know.
Thanks,
Mark
|
 |
smi-mark
DevForce MVP
Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
|
Post Options
Quote Reply
Posted: 11-May-2011 at 12:45pm |
|
Hi Denis,
I have had to work on a couple other projects recently, I will get back to this and create an example showing what I mean.
Thanks,
Mark
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 11-May-2011 at 12:36pm |
Hi smi-mark;
I just want to follow up again on this to make sure that there isn't any other bug.
The code snippet in your last post seems to be similar to what I'm doing in my testing but I'm still having a hard time understanding when you said ""Using AcceptChanges or SetModified by it self didn't work".
I would appreciate it if you can clarify that to me so I know all the bugs related to this that could be discovered are discovered.
Thanks!
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 25-Apr-2011 at 11:48am |
Thanks for sharing your solution smi-mark.
Could you clarify what you meant by "Using AcceptChanges or SetModified by it self didn't work" ?
What do you mean by itself and what didn't work?
|
 |
smi-mark
DevForce MVP
Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
|
Post Options
Quote Reply
Posted: 22-Apr-2011 at 11:20am |
Hi Denis, Using AcceptChanges or SetModified by it self didn't work, but I do seem to have a solution: I create a list of entities from EM2 with a state of Added, call AcceptChanges, import to EM1 For each Added Entity in EM2 i find the Entity using FindEntity EntityKey in EM1 and call SetAdded on it, this keeps the temporary Id and seems to work.
var addedEntities = fromManager.FindEntities(EntityState.Added)
.OfType<Entity>()
.ToList();
addedEntities.ForEach(e => e.EntityAspect.AcceptChanges());
toManager.ImportEntities(addedEntities, MergeStrategy.OverwriteChanges);
addedEntities.Select(entity => toManager.FindEntity(entity.EntityAspect.EntityKey) as Entity)
.ForEach(e => e.EntityAspect.SetAdded());
|
Edited by smi-mark - 22-Apr-2011 at 11:21am
|
 |
smi-mark
DevForce MVP
Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
|
Post Options
Quote Reply
Posted: 20-Apr-2011 at 3:46pm |
|
Hi Denis,
Perfect, if that is the case then that will work fine.
Thanks for looking into it.
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 20-Apr-2011 at 1:53pm |
Hi smi-mark;
If the new "modified" entity still has a temp id, upon call to SaveChanges, EntityManager will do an id fixup and insert that new entity into the database. It will not update an existing entity in the database.
As I've mentioned before, you could also call AcceptChanges on CustomerAddress before EM2 saves/merges the entity back into EM1. I believe this will work better since you can call RejectChanges to roll back any Modified entity back to its Unchanged state.
|
 |
smi-mark
DevForce MVP
Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
|
Post Options
Quote Reply
Posted: 19-Apr-2011 at 1:33pm |
|
Hi Denis,
I need to test this, but in a "modified" state, won't they try to update in the database rather than inserting them? These are new entities that have not yet been saved.
This is being used in a sandbox scenario such as this:
Customer - EM 1 Customer Address Edit - EM 2
When EM 2 "saves" it does not really save, it simply merges back into EM 1. EM 1 is responsible for saving of any changes.
I am doing it like this to simulate the old checkpointing ability in DevForce classic.
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 19-Apr-2011 at 1:08pm |
Hi smi-mark;
I've discussed the issue regarding importing entity with an Added state and temp id resulting in a duplicate entity with the lead developer and confirmed that this is the correct behavior.
The reason is that, when the entity is still in the Added state and has a temp id, EntityManager still considers it as a new entity and so when another same entity with the same temp id is also imported, EM will consider that entity a "new" entity and assigns it a new temp id.
The workaround by setting that entity to Modified, (calling AcceptChanges will work as well), is correct because we're telling the EntityManager that the entity is no longer new as we have "touched" it.
Please let me know if you still have further questions. I will post more updates on the PropertyChanged issue when I have some.
Edited by DenisK - 19-Apr-2011 at 1:10pm
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 01-Apr-2011 at 4:38pm |
|
Thanks again smi-mark. This is really helpful.
|
 |
smi-mark
DevForce MVP
Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
|
Post Options
Quote Reply
Posted: 01-Apr-2011 at 3:51pm |
|
I have found a workaround for both problems.
For the first problem, as above, I just call it twice.
For the second problem, I do it like this:
public static void ImportFrom(this EntityManager manager, EntityManager fromManager) { var addedEntities = fromManager.FindEntities(EntityState.Added).OfType<Entity>().ToList(); fromManager.RemoveEntities(addedEntities); manager.ImportEntities(fromManager.FindEntities(EntityState.AllButDetached), MergeStrategy.OverwriteChanges); manager.AddEntities(addedEntities); }
Edited by smi-mark - 01-Apr-2011 at 4:16pm
|
 |
DenisK
IdeaBlade
Joined: 25-Aug-2010
Posts: 715
|
Post Options
Quote Reply
Posted: 01-Apr-2011 at 10:01am |
|
|
 |
smi-mark
DevForce MVP
Joined: 24-Feb-2009
Location: Dallas, Texas
Posts: 343
|
Post Options
Quote Reply
Posted: 31-Mar-2011 at 7:52pm |
|
Hi Denis,
This how you can reproduce it:
var mgr1 = new TestEntities(); var mgr2 = new TestEntities();
var customer = mgr1.CreateEntity<Customer>(); customer.Name = "Test";
mgr1.AddEntity(customer);
mgr2.ImportEntities(mgr1.FindEntities<Customer>(EntityState.AllButDetached), MergeStrategy.OverwriteChanges);
Console.WriteLine("Mgr1 count {0} Mgr2 count {1}", mgr1.FindEntities<Customer>(EntityState.AllButDetached).Count(), mgr2.FindEntities<Customer>(EntityState.AllButDetached).Count());
mgr1.ImportEntities(mgr2.FindEntities<Customer>(EntityState.AllButDetached), MergeStrategy.OverwriteChanges);
Console.WriteLine("Mgr1 count {0} Mgr2 count {1}", mgr1.FindEntities<Customer>(EntityState.AllButDetached).Count(), mgr2.FindEntities<Customer>(EntityState.AllButDetached).Count());
foreach (var c in mgr1.FindEntities<Customer>(EntityState.AnyAddedModifiedOrDeleted)) { Console.WriteLine("{0} {1}", c.Id, c.Name); }
You will see mgr1 now has the same entity twice, but with a different id
Edited by smi-mark - 31-Mar-2011 at 7:59pm
|
 |