Author |
Share Topic Topic Search Topic Options
|
skingaby
DevForce MVP
Joined: 23-Apr-2008
Location: United States
Posts: 146
|
Post Options
Quote Reply
Topic: Handling Concurrency Failures Posted: 09-Oct-2009 at 1:48pm |
So I am trying to implement some sort of concurrency management in Silverlight. It seems like I am barking up the wrong tree.
I started from the IdeaBlade DevForce\Learning Resources\040_BusObjPersistence\ConcurrencyConflicts\Samples\300WNF_WinForms\CodeCS.
Of course, this is a WinForms example, so it doesn't translate well.
On the client, we call this:
public void SaveItemList(IList<BaseEntity> itemList, Action<EntitySavedEventArgs> saveCompletedAction)
{
List<BaseEntity> saveList = new List<BaseEntity>();
foreach (BaseEntity item in itemList)
{
if (item.EntityAspect.HasChanges())
{
saveList.Add(item);
}
}
if (saveList.Count != 0)
{
EntityManager.SaveChangesAsync(saveList, args => SaveCallback(args, saveCompletedAction), userState);
}
}
protected void SaveCallback(EntitySavedEventArgs args, Action<EntitySavedEventArgs> saveCompletedAction)
{
if (args.Error != null)
{
var saveException = args.Exception as EntityManagerSaveException;
if (saveException != null)
{
switch (saveException.FailureType)
{
case PersistenceFailure.Concurrency:
ConcurrencyHandler.ConflictScenario aConflictScenario =
ConcurrencyHandler.HandleConcurrencyException(saveException,
ConcurrencyHandler.ConcurrencyResolutionStyle.DatabaseVersionWins); //try a simple handler first
break;
...
}
}
}
saveCompletedAction(args);
}
The ConcurrencyHandler looks like this:
public static ConflictScenario HandleConcurrencyException(EntityManagerSaveException saveException, ConcurrencyResolutionStyle pResolutionStyle)
{
if (saveException.EntitiesWithErrors.Count > 0)
{
_entitiesWithErrors = (IList<BaseEntity>)saveException.EntitiesWithErrors; //COLLECTION IS EMPTY
}
switch (pResolutionStyle)
{
case ConcurrencyResolutionStyle.DatabaseVersionWins:
KeepDatabaseChanges();
return ConflictScenario.NotDiscriminated;
}
}
private static IList<BaseEntity> _entitiesWithErrors;
private static EntityKeyList _keyList;
private static void KeepDatabaseChanges()
{
var keys = new List<EntityKey>();
foreach (Entity entityWithError in _entitiesWithErrors)
{
keys.Add(entityWithError.EntityAspect.EntityKey);
}
_keyList = new EntityKeyList(_entitiesWithErrors[0].GetType(), keys); //THIS IS WRONG
var em = LocalEntityManager.DefaultManager;
em.RefetchEntitiesAsync(_keyList, MergeStrategy.OverwriteChanges, RefetchCompleted, null);
} //KeepDatabaseChanges
public static void RefetchCompleted(AsyncEventArgs args)
{
if (args.Error != null)
{
foreach (BaseEntity entityWithError in _entitiesWithErrors)
{
//entityWithError.ForceRefreshInUI(); //HOW?????
}
}
}
Here are the problems I can't seem to work around. Any suggestions would be welcome.
1) saveException.EntitiesWithErrors is an empty collection, I had expected it to be populated with the entities that have a concurrency error;
2) EntityKeyList is type specific, but the EntitiesWithErrors collection is not and could have a mixture of types in it; i.e. the code above will fail because the entities being saved include Orders and OrderDetails, but the EntityKeyList will get the Type of the first one in its constructor new EntityKeyList(_entitiesWithErrors[0].GetType(), keys);
3) RefetchEntitiesAsync docs say it is a beta feature, so should I not be using it yet? Is there some other way to refetch asynchronously?
4) The entities in the UI are held in an ObservableCollection that is created in the ViewModel when the query.ExecuteAsync calls back, like so:
private void GetDealsCallback(EntityFetchedEventArgs<Deal> args)
{
var results = args.Result;
var sortedResults = from item in results orderby item.LastUpdateTms descending select item;
var obsColl = TypeHelper.CreateObservableCollection<Deal>(sortedResults);
this.DealListInternal = obsColl; //THE UI GRID IS BOUND TO DEALLISTINTERNAL
}
Once the entities are "refetched", how can I force the UI to refresh the relevant rows in the grid? I am going to have the same problem when I auto-update the entities in the cache on a push (which we have to implement somehow too, but that's a seperate post).
|
|
GregD
IdeaBlade
Joined: 09-May-2007
Posts: 374
|
Post Options
Quote Reply
Posted: 13-Oct-2009 at 6:46am |
Simon, I'm working on a Silverlight implementation of concurrency handling and will let you know something shortly.
|
|
GregD
IdeaBlade
Joined: 09-May-2007
Posts: 374
|
Post Options
Quote Reply
Posted: 13-Oct-2009 at 1:32pm |
Simon:
In attempting to create a Silverlight solution, I reproduced the same issue you report, which is that the EntitiesWithErrors list is empty, when it shouldn't be. (Note that it will only ever contain a single entity, as saves are transactional and one entity at a time.)
At Kim's behest I have filed a Very High priority bug for this.
|
|
skingaby
DevForce MVP
Joined: 23-Apr-2008
Location: United States
Posts: 146
|
Post Options
Quote Reply
Posted: 14-Oct-2009 at 10:40am |
Cool. Thank you.
|
|
skingaby
DevForce MVP
Joined: 23-Apr-2008
Location: United States
Posts: 146
|
Post Options
Quote Reply
Posted: 17-Oct-2009 at 1:02pm |
Greg, you say the list "will only ever contain a single entity". But the EntityManager.SaveChangesAsync method is saving ALL the dirty entities in a transaction, not just one at a time. Oh, I get it. The save will fail on the first concurrency (or any other) failure and that will be the entity in the "EntitiesWithErrors" collection. Right?
|
|
GregD
IdeaBlade
Joined: 09-May-2007
Posts: 374
|
Post Options
Quote Reply
Posted: 19-Oct-2009 at 11:45am |
Yes, that's correct.
|
|
cjohnson84
Groupie
Joined: 24-Sep-2009
Location: Akron, Ohio
Posts: 44
|
Post Options
Quote Reply
Posted: 21-Dec-2009 at 7:39am |
Did the problem involving the EntitiesWithErrors being empty ever get resolved? I am trying to implement concurrency handling in my DevForce Silverlight application following the same methodology described above and I'm finding the EntitieswithErrors collection is still empty. I am using DevForce Silverlight 5.2.3.1.
|
|
skingaby
DevForce MVP
Joined: 23-Apr-2008
Location: United States
Posts: 146
|
Post Options
Quote Reply
Posted: 21-Dec-2009 at 4:13pm |
One thing someone at IB said was that the Domain Model namespace and the Domain Model project namespace should be the same. The bug was that when they weren't, the EntitiesWithErrors was always empty. I also think they fixed it in 5.2.4.2, but I am not sure. I have been completely rebuilding my domain projects and my app classes, so I have not been able to work on concurrency in a while.
|
|
cjohnson84
Groupie
Joined: 24-Sep-2009
Location: Akron, Ohio
Posts: 44
|
Post Options
Quote Reply
Posted: 22-Dec-2009 at 5:36am |
I verified that my Domain Model and my Domain Model project have the same namespace. Is version 5.2.4.2 available for download? I'm not seeing it on the website.
|
|
skingaby
DevForce MVP
Joined: 23-Apr-2008
Location: United States
Posts: 146
|
Post Options
Quote Reply
Posted: 22-Dec-2009 at 6:08am |
Yes.
|
|
skingaby
DevForce MVP
Joined: 23-Apr-2008
Location: United States
Posts: 146
|
Post Options
Quote Reply
Posted: 22-Dec-2009 at 6:10am |
I am not sure then. Hopefully kimj will chime in and remind us what the setup needs to be to catch the concurrency failure. I will be looking at it again in the next couple of days. (I finally got my completely redone solution working last night. Yay!)
|
|
cjohnson84
Groupie
Joined: 24-Sep-2009
Location: Akron, Ohio
Posts: 44
|
Post Options
Quote Reply
Posted: 22-Dec-2009 at 6:12am |
I'm downloading 5.2.4.2 now. I didn't realize it was released. I'm going to try it and see what happens. Thank you for your help! I appreciate it!
|
|
cjohnson84
Groupie
Joined: 24-Sep-2009
Location: Akron, Ohio
Posts: 44
|
Post Options
Quote Reply
Posted: 22-Dec-2009 at 7:10am |
I verfied the problem is fixed in 5.2.4.2. Thank you skingaby for your help!
|
|
kimj
IdeaBlade
Joined: 09-May-2007
Posts: 1391
|
Post Options
Quote Reply
Posted: 22-Dec-2009 at 9:01am |
Thanks Simon. I just saw this question yesterday afternoon, and Simon beat me to answering it this morning.
We normally announce the availability of a new release here on the forum, but 5.2.4.x turned out to be a somewhat stealth release. You can always find the latest version and release notes on the Resources/Documentation page of our web site when in doubt.
|
|
cjohnson84
Groupie
Joined: 24-Sep-2009
Location: Akron, Ohio
Posts: 44
|
Post Options
Quote Reply
Posted: 05-Jan-2010 at 7:07am |
Was a Silverlight implementation of concurrency handling ever completed as mentioned above? If so is it available somewhere to download? The only sample in the Learning Resources is for WinForms.
|
|
GregD
IdeaBlade
Joined: 09-May-2007
Posts: 374
|
Post Options
Quote Reply
Posted: 05-Jan-2010 at 11:19am |
Sorry, no Silverlight sample yet, but I'll put it on our list.
|
|