Linq / Entities: all or nothing (in the database)

I am trying to implement a way to put data (object objects) into a database only in case of an error ("all"). If an error occurs, nothing is created in the database ("or nothing"). What I call "all or nothing."

The problem is that I have to create objects that depend on other objects. Here is an example:

0) I create a context

DBContext ctx = new DBContext(); 

1) I create an account entity object and add it to the context:

 Invoice inv1 = new Invoice(); inv1 .Number = "Invoice-2546432"; if(!ctx.Invoice.Exists(i => i.Number == "Invoice-2546432")) // problem n°1 ctx.AddObject(inv1 ); else throws new Exception('blah blah'); 

2) The invoice has invoice lines:

 InvoiceLine line = new InvoiceLine(); line .ID_INVOICE = in1.ID; // problem n°2 line .Label = "Line 1"; line .Ammount = 5.3; ctx.AddObject(line ); 

3) Finally:

 ctx.SaveChanges(); 

So, if everything goes well, I have something like this:

  Table INVOICE ===================== ID | NUMBER _____________________ 0 | Invoice-2454876 _____________________ 1 | Invoice-2487432 _____________________ 2 | Invoice-2546432 Table INVOICE_LINE ========================================= ID | ID_INVOICE | LABEL | AMOUNT _________________________________________ 0 | 0 | Line 1 | 2.6 _________________________________________ 1 | 0 | Line 2 | 7.6 _________________________________________ 2 | 1 | Line 1 | 7.6 _________________________________________ 3 | 2 | Line 1 | 8.6 _________________________________________ 

As mentioned in the comments, there are two problems:

Task n ° 1:

The existence test always returns false, because it only checks in the database, and not in the context itself, where I just added a new object.

Task n ° 2:

Since the invoice is only added to the context and not to the database, I do not have an identifier for the future invoice. Therefore, I cannot set it in the account line.

1) Do you know how to do this, basically, a safe way to add data to a database? I am developing a financial application, and I want to make sure that there is no corrupted data in the database (for example: if the insertion of the account line failed, I want the entire account not to be inserted into the database)

2) I did not find design patterns related to such things. Do you know anyone by chance?

3) I'm not sure that I understood the context objects in the entity infrastructure well: Here is my understanding:

Context is a (mostly) database connection. When I add an object, it is saved somewhere in memory and inserted into the database after calling SaveChanges (). It's right? Do you know any site or book detailing how the ADO / entity structure works?

+4
source share
2 answers

It seems that you are still thinking in sql or record thinking - EF is ORM and does most of the low-level housekeeping that you described.

Ideally, since it seems clear that there is a 1: many relationship between Invoice and InvoiceLine , you should model this 1: N relationship in EF and then let EF worry about fixing / assigning the identity column, i.e.

 Invoice invoice = new Invoice(); invoice.InvoiceLines.Add(new InvoiceLine() { ... set fields here }) ... add more details // Now add just the invoice to the context. The lines will be added automatically ctx.AddObject(invoice); ctx.SaveChanges(); 

To answer the second question, you can use TransactionScope() to combine several database operations in one unit of work.

To answer your last question — you should not think of context as connecting to a database — this is a higher-level concept that governs the state of the entities that govern it.

Also note that SaveChanges() itself must ensure that all changes in the context are saved in the transaction, so you usually don't need additional transaction management if you use the same context.

Should these SO posts here and here help?

+6
source

To answer your question, you can add an additional field to the table of accounts, for example, “Status as a bit”. If all your account lines are saved without any exceptions, you will finally update the corresponding account and set Status = true.

Using TransactionScope makes the logic very complex. transactioncope is not intelligent enough to understand everything.

-1
source

All Articles