Connection.BeginTransaction and Entity Framework 4? - entity-framework-4

I am trying to use transactions with EF4 Code-first with an unit of work implementation. Is there a reason we cannot use Connection.BeginTransaction from the context ? It is only intended to be used in SQL transactions only ? Because when im calling it i get the error : Illegal operation. Connection is closed.
Thanks.

Part of the answer will be that DbContext.SaveChanges() is automatically transactional, so in many cases, you will not need to roll your own transactions. What is your scenario, and why do you think that you need to manually do transactions?
If you decide you need them, wrap SaveChanges in a transaction:
using (TransactionScope transaction = new TransactionScope())
{
context.SaveChanges();
}
If you run Profiler, you will note that the transaction is rolled back once you leave the using{} block. To commit your transaction, call transaction.Complete(); after SaveChanges().

Related

How to rollback previous changes in ef codefirst model

I am working on asp.net mvc with EF codefirst. I am trying to update the list of records at once. like,
foreach(var pat in listpats)
{
context.Entry<Patient>(pat).state=EntityState.Modified;
context.savechanges();
}
and its working fine for me. Now suppose if listpats contains 10 items, if i got exception at 7th item while i am updating. it will save first 6 items. but i want to save all records at once if no error occurred while updating. if any error occurred mean while i should rollback all the previous changes. so how could i achieve this using EF code first model. please guide me.
You should invoke SaveChanges() outside foreach:
foreach(var pat in listpats)
{
context.Entry<Patient>(pat).state=EntityState.Modified;
}
context.SaveChanges();
This way if an exception occurs everything will be rolled back
If you've modified the entities in some other code then their state will be modified (within the same context) without you having to explicitly change it with a foreach loop and context.Entry(pat).state=EntityState.Modified.
So taking a step back, after you've modified all your patients entities a single call to context.SaveChanges() will automagically rollback on error.
Soooo to summarise, change all the patients entities and afterwards call context.SaveChanges() which will make EF propogate all the entities that have a modified state (the state change happens when you modify the entity) to the DB, context.SaveChanges() will handle simple cases like this with regards to rollback.
P.S. Your question is making me wonder if you've changed the patients in a different context and that's why your manually changing the current context' state.

Pattern to overcome the lack of a ConflictMode.ContinueOnConflict implementation in the Entity Framework?

Linq To SQL's DataContext has an overload on SubmitChanges that allows for updates to continue when a Optimistic Concurrency Exception is thrown, and provides the developer with a mechanism to resolve the conflicts afterwards in a single Try Catch block.
Even the WCFDataServicesContext has a SaveChangedOptions.ContinueOnError parameter for its SaveChanges method that at least allows you to continue updating when an error has occurred and leaves conflicting updates unresolved so you can look into them later.
(1) Why then does the ObjectContext.SaveChanges method have no such option?
(2) Do any update patterns exist that will mimick the Linq To SQL behaviour? The examples I find on MSDN make it appear as if a single Try Catch block will see you home in the case of multiple updates. But this pattern does not allow you to investigate each conflicting update separately: it just alerts you to the first conflict and then gives you the option to "wipe the table clean in one sweep" to prevent any further optimistic concurrency exceptions from surfacing, without your knowing if any exist and what you would have liked to do about them.
Why then does the ObjectContext.SaveChanges method have no such option?
I think the simplest answer is because Linq-to-Sql, Entity Framework and WCF Data Services were all implemented by different teams and internal communication among these teams doesn't work as we would hope. I have described some interesting features missing in newer APIs in one of my former answers but I don't think this is a missing feature - I will explain it in the second part of my answer.
WCF Data Services have more interesting features which should be part of Entity framework as well. For example:
Change and Query interceptors
Batching multiple queries and SaveChanges operations to single call to server
Asynchronous operations - this will come to EF6 in form of async/await implementation
Do any update patterns exist that will mimick the Linq To SQL behaviour?
There is a pattern how to solve this but you will probably not like it. EF's SaveChanges works as Unit of work. It either saves all changes or none. If you have a scenario where your saving operation can result in case where only part of your changes is persisted than it should not be handled by single SaveChanges call. Each atomic set of changes should have its own SaveChanges call:
using (var scope = new TransactionScope(...)) {
foreach (var entity in someEntitiesToModify) {
try {
context.SomeEntities.Attach(entity);
context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
context.SaveChanges();
catch (OptimisticConcurrencyException e) {
// Do something here
context.Refresh(e.StateEntries[0].Entity, RefreshMode.ClientWins);
context.SaveChanges();
}
}
scope.Complete();
}
I think the reason why this feature doesn't exist is because it is not generic and as mentioned about it goes against unit of work pattern. Suppose this example:
You load an entity
You add a new dependent entity to navigation property of your loaded entity
You change something on the loaded entity
In the mean time somebody else concurrently delete your loaded entity
You trigger SaveChanges with relaxed conflict resolution
EF will try to save changes to the principal entity but it conflicts because there is no entity to update in the database
EF will continue because conflict resolution is relaxed
EF will try to insert dependent entity but it will fire SqlException because the principal entity doesn't exist in the database. This exception will break the persistence operation and you will not know why it is complaining about referential integrity because you have a principal entity. (It is possible that this insert will even not happen and EF fires another exception due to inconsistency of context's inner state but it depends on EF's internal implementation).
This immediately makes whole relaxing of conflict resolution much more complex feature. There are IMHO three ways to solve it:
Simply not support it. If you need conflict resolution per entity basis you can still use the example I showed above but for complex scenarios it may not work because complex scenarios are hard to solve.
Rebuild database change set each time the conflict occurs - it means to explore the remaining change set and exclude all entities related to conflicting entity and their relations an so on from the processed persistence. There is a problem: EF cannot exclude any changed entity from processing. That would break the meaning of unit of work and I repeat it one more: Relaxing conflict resolution can also break meaning of unit of work.
Let EF to proceed with dependencies even if the principal entity conflicted. This requires to handle the database exception and understand its content to know if the exception is fired due to conflicting principal or due to other error (which should fail whole persistence operation immediately). It can be quite difficult to understand database exceptions on the code level and moreover it is provider specific for every supported database.
It doesn't mean it may not be possible to make such functionality but it will need to cover all scenarios when it comes to relations and this can be pretty complex. I'm not sure if Linq-to-Sql handles this.
You can always make a suggestion on Data UserVoice or check out the code and try to implement it yourselves. Maybe I see this feature too complicated and it can be implemented easily.

linq: SQL performance on high loaded web applications

I started working with linq to SQL several weeks ago. I got really tired of working with SQL server directly through the SQL queries (sqldatareader, sqlcommand and all this good stuff). 
After hearing about linq to SQL and mvc I quickly moved all my projects to these technologies. I expected linq to SQL work slower but it suprisongly turned out to be pretty fast, primarily because I always forgot to close my connections when using datareaders. Now I don't have to worry about it.
But there's one problem that really bothers me. There's one page that's requested thousands of times a day. The system gets data in the beginning, works with it and updates it. Primarily the updates are ++ # -- (increase and decrease values). I used to do it like this
UPDATE table SET value=value+1 WHERE ID=#I'd
It worked with no problems obviously. But with linq to SQL the data is taken in the beginning, moved to the class, changed and then saved.
Stats.registeredusers++;
Db.submitchanges();
Let's say there were 100 000 users. Linq will say "let it be 100 001" instead of "let it be increased by 1".
But if there value of users has already been increased (that happens in my site all the time) then linq will be like oops, this value is already 100 001. Whatever I'll throw an exception"
You can change this behavior so that it won't throw an exception but it still will not set the value to 100 002.
Like I said, it happened with me all the time. The stas value was increased twice a second on average. I simply had to rewrite this chunk of code with classic ado net.
So my question is how can you solve the problem with linq
For these types of "write-only queries" I usually use a Stored Procedure. You can drag the stored procedure into the designer and execute it through the Linq to SQL DataContext class (it will be added as a method).
Sorry for the trite answer but it really is that simple; no need to to finagle with raw ADO.NET SqlCommand objects and the like, just import the SP and you're done. Or, if you want to go really ad-hoc, use the ExecuteCommand method, as in:
context.ExecuteCommand("UPDATE table SET value = value + 1 WHERE ID = {0}", id);
(But don't overuse this, it can get difficult to maintain since the logic is no longer contained in your DataContext instance. And before anybody jumps on this claiming it to be a SQL injection vulnerability, please note that ExecuteCommand/ExecuteQuery are smart methods that turn this into a parameterized statement/query.)
Linq to Sql supports "optimistic" concurrency out of the box. If you need tighter control, you can add a Timestamp column to your table, and Linq to Sql will use that timestamp to tighten the concurrency.
http://mtaulty.com/CommunityServer/blogs/mike_taultys_blog/archive/2008/07/01/10557.aspx
However, as Morten points out in the comments below, this solution is not going to perform well. Of course, you can always use ADO.NET to update the value, just like you were doing before; that won't adversely affect the operation of your Linq queries at all.
You could turn off concurrency on that property by changing the UpdateCheck value:
http://msdn.microsoft.com/en-us/library/bb399394(v=VS.90).aspx
Messy if your using generated code and the designer but I think this is the only way to do this.

NHibernate: how to handle entity-based validation using session-per-request pattern, without controllers knowing about ISession

What is the best way to do entity-based validation (each entity class has an IsValid() method that validates its internal members) in ASP.NET MVC, with a "session-per-request" model, where the controller has zero (or limited) knowledge of the ISession? Here's the pattern I'm using:
Get an entity by ID, using an IFooRepository that wraps the current NH session. This returns a connected entity instance.
Load the entity with potentially invalid data, coming from the form post.
Validate the entity by callings its IsValid() method.
If valid, call IFooRepository.Save(entity), which delegates to ISession.Save(). Otherwise, display error message.
The session is currently opened when the request begins and flushed when the request ends. Since my entity is connected to a session, flushing the session attempts to save the changes even if the object is invalid.
What's the best way to keep validation logic in the entity class, limit controller knowledge of NH, and avoid saving invalid changes at the end of a request?
Option 1: Explicitly evict on validation failure, implicitly flush: if the validation fails, I could manually evict the invalid object in the action method. If successful, I do nothing and the session is automatically flushed.
Con: error prone and counter-intuitive ("I didn't call .Save(), why are my invalid changes being saved anyways?")
Option 2: Explicitly flush, do nothing by default: By default I can dispose of the session on request end, only flushing if the controller indicates success. I'd probably create a SaveChanges() method in my base controller that sets a flag indicating success, and then query this flag when closing the session at request end.
Pro: More intuitive to troubleshoot if dev forgets this step [relative to option 1]
Con: I have to call IRepository.Save(entity)' and SaveChanges().
Option 3: Always work with disconnected objects: I could modify my repositories to return disconnected/transient objects, and modify the Repo.Save() method to re-attach them.
Pro: Most intuitive, given that controllers don't know about NH.
Con: Does this defeat many of the benefits I'd get from NH?
Option 1 without a doubt. It's not counter intuitive, it's how NH works. Objects retrieved using NH are persistent and changes will be saved when the session is flushed. Calling Evict makes the object transient which is exactly the behavior you want.
You don't mention it but another option might be to use Manual or Commit FlushMode.
How about a validation service with an IsValid (or something similar) method which validates the object passed to it, if it fails it could publish a ValidationFailed event. Then when your request finishes instead of calling the session's flush you could publish a RequestEnd event. You could then have a handler that listens for both RequestEnd events and ValidationFailed events - if there is a ValidationFailed event then don't flush the session but if not then flush it.
Having said that I just do Option 2!
As Mauricio and Jamie have pointed out in their answers/comments, it's not easy (and probably not desirable) to do exactly what the question asks. NH returns persistent objects, so exposing those objects to the controllers means the controllers are responsible for treating them as such. I want to use lazy loading, so exposing detached instances won't work.
Option 4: Introduce a new pattern that provides the desired semantics
The point of this question is that I'm introducing NH+Repositories to an existing project using a hand-rolled, Active-Record-like DAL. I want code written NH to use patterns similar to the legacy code.
I created a new class called UnitOfWork that is a very thin wrapper over an ITransaction and that knows how to access the ambient session related to the current HttpRequest. This class is designed to be used in a using block, similar to TransactionScope which the team is familiar with:
using (var tx = new UnitOfWork()) {
var entity = FooRepository.GetById(x);
entity.Title = "Potentially Invalid Data";
if (!entity.IsValid()) {
tx.DiscardChanges();
return View("ReloadTheCurrentView");
}
else {
tx.Success();
return RedirectToAction("Success");
}
}
The tx.DiscardChanges() is optional, this class has the same semantics as TransactionScope which means it will implicitly rollback if it is disposed before the success flag is set.
On a greenfield NH project I think it's preferable to use Option 1, as Jamie indicates in his answer. But I think Option 4 is a decent way to introduce NH on a legacy project that already uses similar patterns.

Updating a disconnected LINQ object with MVC Framework RC1

This is a little out there but I have a customer object coming back to my controller. I want to just reconnect this object back to the database, is it even possible? I know there is a datacontext.customers.insertonsubmit(customer), but is there the equivalent datacontext.customers.updateonsubmit(customer)???
This is what I don't like about LINQ-to-SQL.
It generally works fine if you're querying and updating in the same scope, but if you get an object, cache it, and then try to update it later, you can't.
Here's what the documentation says:
Use the Attach methods with entities that have been created in one DataContext, and serialized to a client, and then deserialized back with the intention to perform an update or delete operation. Because the new DataContext has no way of tracking what the original values were for a disconnected entity, the client is responsible for supplying those values. In this version of Attach, the entity is assumed to be in its original value state. After calling this method, you can then update its fields, for example with additional data sent from the client.
Do not try to Attach an entity that has not been detached through serialization. Entities that have not been serialized still maintain associations with deferred loaders that can cause unexpected results if the entity becomes tracked by a second data context.
A little ambiguous IMHO, specifically about exactly what it means by "serialized" and "deserialized".
Also, interestingly enough, here's what it says about the DataContext object:
In general, a DataContext instance is
designed to last for one "unit of
work" however your application defines
that term. A DataContext is
lightweight and is not expensive to
create. A typical LINQ to SQL
application creates DataContext
instances at method scope or as a
member of short-lived classes that
represent a logical set of related
database operations.
So, DataContexts are intended to be tightly scoped - and yet to use Attach(), you have to use the same DataContext that queried the object. I'm assuming/hoping we're all completely misunderstanding what Attach() is really intended to be used for.
What I've had to do in situations like this is re-query the object I needed to update to get a fresh copy, and then do the update.
The customer that you post from the form will not have entity keys so may not attach well, also you may not have every field of the customer available on the form so all of it's fields may not be set.
I would recommend using the TryUpdateModel method, in your action you'll have to get the customer from the database again and update it with the form's post variables.
public ActionResult MySaveAction(int id, FormCollection form)
{
Customer updateCustomer = _Repository.GetCustomer(id);
TryUpdateModel(updateCustomer, "Customer", form);
_Repository.Save(updateCustomer);
}
You will have to add in all your own exception handling and validation of course, but that's the general idea.
You want to use the attach method on the customers table on the data context.
datacontext.customers.Attach(customer);
to reconnect it to the data context. Then you can use SubmitChanges() to update the values in the database.
EDIT: This only works with entities that have been detached from the original data context through serialization. If you don't mind the extra call to the database, you can use the idiomatic method in ASP.NET MVC of retrieving the object again and applying your changes via UpdateModel or TryUpdateModel as #Odd suggests.

Resources