Behind every window of the Order Book stands the same class: OrderData. It holds a DataSet, loads it with three adapters,
saves it with a SqlCommandBuilder and reads everything again after every save (break point B4). That has worked for twenty years.
But it has a property that is no good for the web: The program keeps the whole state in the memory of one window, and all forms
share it. A web API (module 4) cannot hold one DataSet for all users.
This lesson builds the data access anew, with Entity Framework Core (EF Core), as the project Brandt.OrderBook.Data next to the
program. The forms stay with the DataSet until lesson M4.2; the new layer is built, tested and reaches the same database. How the
two live together there is the subject of lesson M3.3. What EF Core is and how to use it is in K2, module 2.4 (Data); here you find
only what the Order Book needs in particular.
What the DataSet does, and what takes its place
Before you replace anything, write down what it does. OrderData does more than its name says:
| What the old program does | Where | In the new code |
|---|---|---|
| Load tables into memory | SqlDataAdapter.Fill |
LINQ queries with ToListAsync |
| Hold rows without a type | DataTable, DataRow, row["Status"] |
Classes with properties and enumerations |
| Relations between tables | DataRelation Customer_Orders |
Navigation properties Customer.Orders |
| Number new rows provisionally (negative) | AutoIncrementSeed = -1 |
EF Core assigns provisional values and reads the number back after saving |
| Generate INSERT, UPDATE, DELETE | SqlCommandBuilder |
SaveChangesAsync |
| Detect a simultaneous change | CommandBuilder compares all old values, error DBConcurrencyException |
one concurrency token, error DbUpdateConcurrencyException |
| Read everything again after saving | Save() calls Load() |
one context per operation, short-lived |
| Filter the display | DataView.RowFilter = "Status = '…'" |
LINQ Where with an enumeration instead of text |
The table shows two things. Most of it has a counterpart in EF Core that serves the purpose better. But two rows have no equivalent counterpart without work of your own: the lock over all columns and what the database itself does. More on that in a moment.