4

I think I'm running into a common problem: I would like to try to insert an object to the database. If primary key is violated then I would like to abort the insert. (this is an example, the question really applies to any kind of error and any of the CRUD operations)

How can I discard changes made to EF context?

I can't afford recreating it every time something goes wrong.

PS. I know that perhaps I could check if everything is ok eg. by querying the db, but I don't like the idea. Db constraints are there for some reason and this way it's faster and I have to write less code.

kubal5003
  • 7,186
  • 8
  • 52
  • 90
  • This is a very helpful article which I have used it: http://www.binaryintellect.net/articles/c1bff938-1789-4501-8161-3f38bc465a8b.aspx – FLICKER Apr 11 '23 at 18:30

2 Answers2

1

You can detach inserted entity from ObjectContext. You can also use ObjectStateManager and its method GetObjectStateEntries. In ObjectStateEntry you can modify its state.

The problem is that you are not using technology in supposed way:

I can't afford recreating it every time something goes wrong.

Sure you should because your code doesn't prevent such situations.

PS. I know that perhaps I could check if everything is ok eg. by querying the db, but I don't like the idea. Db constraints are there for some reason and this way it's faster and I have to write less code.

Yes indeed you should check if everything is OK. Calling database to "validate" your data is something that DBAs really like (sarcasm). It is your responsibility to achieve the highest possible validity of your data before you call SaveChanges. I can imagine that many senior developers / team leaders would simply not pass your code through their code review. And btw. in the most cases it is not faster because of inter process or network communication.

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • Thank you for your answer. I need to explain one thing: I'm not saying that I should validate my data on the db. What I'm saying is that if the case was about uniqueness then relying on the PK might be a good choice because I don't need to perform two queries enclosed in a transaction which IS a penalty to performance. – kubal5003 Jan 26 '11 at 23:18
  • @kubal: So I guess you should ask another question about generating unique PK for your entities. Unfortunatelly EF does not have any equivalent to NHibernate generators where HiLo solves exactly this problem. – Ladislav Mrnka Jan 27 '11 at 23:10
  • I've been thinking about what you've told me and I've decided to change my code to check for uniqueness before calling SaveChanges. The main reason for this was that I didn't have any GOOD reasons to violate the general rule. Performance might be a consideration, but after rethinking, not in my case. – kubal5003 Jan 29 '11 at 23:51
0

Try using DbTransaction.

System.Data.Common.DbTransaction _tran = null;


 _tran = _ent.Connection.BeginTransaction();

_tran .Commit (); //after SaveChanges();

and if theres an exception do a rollback.

_tran.Rollback();
franklins
  • 3,710
  • 6
  • 41
  • 56
  • Transactions apply to the database which is not the case. The changes (if PK is violated) are not populated to the DB. The problem is that consecutive call to context.SaveChanges() will try to commit the same changeset which will fail once again. – kubal5003 Jan 26 '11 at 20:50
  • Are you sure? Make sure the BeginTranaction is within the consecutive call. that way you would always start a new transaction before starting your insert. – franklins Jan 26 '11 at 20:54
  • Yes, I am sure. Read this: http://stackoverflow.com/questions/815586/entity-framework-using-transactions-or-savechangesfalse-and-acceptallchanges – kubal5003 Jan 26 '11 at 21:04
  • I just want to undo the context.ObjectSet.AddObject(obj); call. Or if single change cannot be cancelled - cancel all the changes. – kubal5003 Jan 26 '11 at 21:08