This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
SaveChanges(true) gives the option to reset a unit of work. Is there a way to reset a unit of work without saving? I have a loop of code that executes against some items. It performs an action against an item and then moves onto the next. If an item fails then it is marked as failed. The problem I have is that if the failure was caused by the adding or changing of an entity with an invalid state then any further saves on the unit of work to mark it as failed or to continue with the next item will also fail because of the same validation error. Creating a new unit of work each time is an option but a nice Reset() method on the unit of work to flush out all the changes strikes me as simplier and easier. p.s. using LS2 :D |
|
|
We'll put it on the wishlist, but since we won't be backporting it to LightSpeed 2 even if we do do it, I can only offer you the following gem of kludgerrific hacktasticness: public static void PoorMansReset(this IUnitOfWork u) *runs away very quickly* |
|
|
That is the most disgusting hack I have ever seen in my entire life. For shame.
Does each unit of work create a new connection? I already have some sweet code to easily reset a unit of work scope so that the next call to it will get a new unit of work, I'm more concerned with the performance implications of actioning hundreds of items each in their own unit of work. If it does create a new connection each time, will connection pooling help? |
|
|
Yes, each unit of work creates a new connection (unless you use a custom connection strategy). Connection pooling will help up to a point: if you create and dispose hundreds of units of work, then connection pooling will recycle the connections. However, if you have hundreds of units of work alive at the same time, then each one would be holding a live connection (again, unless you use a custom connection strategy), which I believe would defeat pooling. |
|
|
I'm looking for a Reset() method as well.. Or a simple way to discard changes and clear first level cache objects in the unit of work. Was a there eventually a RichMansReset() method implemented in LightSpeed 3?
|
|
|
Correction: Or ideally, I need to refetch an entity and ensure that first/second cache isn't hit (my code knows that the entity has been updated in the database and the cache is probably stale). But also keep the current changes in the unit of work?
|
|
|
You can just load the entity again from a seperate UnitOfWork (which doesnt use the same 2nd level cache as the one associationed with the original UnitOfWork). That will give you a fresh copy of the entity but not have it affect the original UnitOfWork. Keep in mind that only a single copy of the entity can exist in the IdentityMap (1st level cache) of a UnitOfWork, so if you tried to Attach the entity to the original UnitOfWork then any existing entity with the same UniqueId would be detached from the IdentityMap leading to any changes not being saved.
Jeremy |
|
|
That seems excessive/onerous to simply refetch an entity and skip the 1st level cache. In my case, this particular entity instance (product) is unchanged and read-only inside my unit-of-work, whereas other entities in the same unit of work may have been changed and are waiting for the user to trigger uow.SaveChanges(). My viewmodel receives a message to indicate that the product instance has changed in the database and you should refresh/refetch the entity from the database.. I would rather not have to create a new unit of work, fetch the product and attach it to the existing unit of work just to ensure that the data within the product instance is not stale. I was hoping for more like an extension method for a LightSpeed LINQ query to optionally skip caching *cough* :)
|
|
|
Hi, What you need to do is detach an entity from the UnitOfWork and then refetch it. That effectively removes it from the IdentitMap and second level cache. You could then wrap this up in an extension method like (this is off the top of my head): public static void Refresh(this IUnitOfWork uow, Entity e) { uow.Detach(e); } If you need to reset the whole unit of work, then Jeremy's approach is better. I hope that helps, John-Daniel |
|
|
Is there any changes in the Api for resetting the first level of cache since the last activity in this post? Is it a good idea to loop throught all entities in the uow and calling the method detach? In my winforms project, too much changes can occurs in the database at any time and I cannot just create a new uow each time I want to be sure that I really have the latest information from the database. Please, I'm sure you have a nice workaround to reset the uow. Thank you very much. |
|
|
Nope, no change on this front. But I'm a bit puzzled by why you can't just create a new unit of work. Your 'reset' unit of work would have to reload all the same entities as a new UOW, so the only overhead to creating a new UOW is grabbing a connection from the connection pool (in a WinForms application, that will probably be the connection that the old UOW just released!). In a heavily loaded Web application I understand it could be worth optimising that away but in a WinForms app I am a bit surprised it would make a noticeable difference (again, especially given connection pooling). Or are you using a UnitOfWorkScope and the UOW lifecycle is out of your hands? |
|
|
Hi Ivan, The problem is that while a form is open, some information like in drop down list have to be fetch from the database and these information can be different in comparison when the form was created. I know that I can create another uow but the original uow was also injected in many other classes like service and repository and in this case, if I follow your advices, I think I will have to rehydrated my service and repository with the new uow. Am I wrong? I also want to specify that all my uow are injected with ninject and I use the connectionstrategy to use the same connection for the entire application (SingleConnectionStrategy). What is the overhead of creating a lot of uow? I searched on the web to found the best way to prevent creating too many uow but in my case, the only that I found was to have no caching with a single uow and to be able to query again and again the same rows but with data that are changing. Thank you very much. |
|