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.