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
|
Hello, First of all, I want to say thank you for your first class support. You really helped me out previous time, and I just was hoping that there should be really simple question for my stupid question. What is the right sequence to update entity in typical ASP.NET web site. In your sample ASP.NET MVC I see that you load/update/save entity all in the same scope (e.g. method). What I'm trying to achieve is to have entity loaded first, and then update and save it later on. Let's suppose I have Client object. I load it when customer logs in. I keep it the session with repository (inherited from RepositoryBase). Doing this, I presume that LightSpeed keeps all necessary links inside of itself. So when I call ClientRepository.SaveChanges() it will save all changes I did to Client entity loaded few pages back. The problem is, that it doesn't. It throws no exceptions, just swallows it. No updates to DB. However, if I do what you did in example (e.g. reload Client entity, update, and save it back all in one method) it works. I would be wery thankful if point me to any standard workflow I shall to follow to do basic CRUD operations in ASP.NET with your ORM. May be I just doing it wrong, trying to persist Repositories and UnitOfWorkScopes in the session. May be it's not how it was meant to be. May it be the right thing just forget about all of Repositories and UnitOfWorkScopes till the next time I need to load or update the entity, and just drop everything as soon as I get data back. Thank you, Alex |
|
|
Hello Alex, The reason this is happening is that entities have unit of work affinity. When you retrieve your entity from session on the second page, it is still registered with the unit of work from the first page. Your ClientRepository.SaveChanges() method is operating on the current unit of work, the unit of work for the current request; but the entity from session is not registered with that unit of work, so the SaveChanges does not pick up the entity (IUnitOfWork.SaveChanges looks only at its own unit of work). There are a couple of ways around this. One is to use the Attach method to re-register the entity in the current unit of work. However our preferred method is to reload the entity into the current unit of work. So you would put only the ID into the session state, and load the entity with that ID during controller initialisation (or maybe Page_Load if using traditional ASP.NET). You are right that Repositories and UnitOfWorkScopes should not be persisted in the session. In fact the whole point of e.g. PerRequestUnitOfWorkScope is that it creates a per-request unit of work for you. You can create a PerRequestUnitOfWorkScope as part of your Repository, and create a new Repository on each page request, or even each method; or you can have a single static Repository with a PerRequestUnitOfWorkScope member. It doesn't matter what lifecycle you choose for the scope object because it consults the HTTP context rather than retaining state itself. So the typical pattern is something like: 1. Create your repository to have a member variable of type PerRequestUnitOfWorkScope, and instantiate this scope object in the repository constructor. (If you are using RepositoryBase, I think this is all done for you.) 2. During request startup (controller initialisation, Page_Load or Application_BeginRequest depending on your design), create an instance of the Repository object and make this available to other methods (e.g. as a member of the controller class or the page class). (You could also use a shared singleton Repository object as long as the Repository object does not itself maintain state (except for the state implicit held in the unit of work).) 3. Get the entity's ID from session state (or the request data, or wherever). 4. Call your repository's FindOne wrapper to load the entity (into the current unit of work). This will just call on to Scope.Current.FindOne. (The scope object will create a unit of work for the request at this point, if it hasn't done so already.) 5. Update the entity using the request data. 6. Call your repository's SaveChanges wrapper. This will call on to Scope.Current.SaveChanges. Scope.Current will be the same UOW that got created in step 4, so your entity is registered in the UOW that's being saved. 7. Call Scope.Current.Dispose to release the database connection. (I generally advise that you should not call Scope.Dispose even though scopes are IDisposable, though this is really only an issue if you are sharing the scope object.) If you are performing progressive updates on an entity, e.g. in a wizard-style UI, then this workflow needs to be modified a bit, because you don't want to save interim changes. In this case you can either use the Attach strategy, save pending changes in session state or build up the request using e.g. hidden fields. If this is your scenario then let me know and I will get Jeremy or JD to post some guidance as I believe they have implemented this scenario in some of our own applications and will have a better idea of the best approach than I do! |
|