Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/karenpayneoregon/efcore-datagridview-tobindinglist

How to work with a DataGridView with EF Core 5
https://github.com/karenpayneoregon/efcore-datagridview-tobindinglist

csharp efcore5 windowsforms

Last synced: about 1 month ago
JSON representation

How to work with a DataGridView with EF Core 5

Awesome Lists containing this project

README

        

# WinForms DataGridView with EF Core 5

## :warning: Note

The inital run of the application will not have any records, use the add button to add data.

---

Typically when a developer new to working with database data in a Windows Form application tend to `add rows` directly to the DataGridView rather than set the DataGridView `DataSource property` which means more code rather than setting the DataGridView DataSource property using a DataSet or DataTable.

When setting the `DataSource property` for a [DataGridView](https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridview?view=windowsdesktop-6.0) to a [DataTable](https://docs.microsoft.com/en-us/dotnet/api/system.data.datatable?view=net-6.0) or [DataSet](https://docs.microsoft.com/en-us/dotnet/api/system.data.dataset?view=net-6.0) then perform save operations all works as expected. This is not the case when working with Entity Framework Core 5 (EF Core 5).

**Basic mistake** where adding a new record (as shown in `Form1`) will not display the new record in the DataGridView.

```csharp
private async void OnShown(object sender, EventArgs e)
{
var list = await DataOperations.People();
dataGridView1.DataSource = list;
}
```

**Next level** is to use a BindingList<T>, in this case BindingList<`Person`>.

The key is [ToBindingList()](https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.observablecollectionextensions.tobindinglist?view=efcore-5.0) extension method.

```csharp
public static async Task> PeopleLocal()
{
return await Task.Run(async () =>
{
await Context.Person.LoadAsync();
return Context.Person.Local.ToBindingList();
});
}
```

In Form2 data is load

```sharp
private async void OnShown(object sender, EventArgs e)
{
BindingList peopleLocalList = await DataOperations.PeopleLocal();
dataGridView1.DataSource = peopleLocalList;
}
```

Now when adding a new Person record the record is displayed in the DataGridView.

**Even better** is to incorporate a [BindingSource](https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.bindingsource?view=net-5.0) which provides navigation ability, useful methods and events.

```csharp
private readonly BindingSource _bindingSource = new BindingSource();

private async void OnShown(object sender, EventArgs e)
{
BindingList peopleLocalList = await DataOperations.PeopleLocal();
_bindingSource.DataSource = peopleLocalList;

dataGridView1.DataSource = _bindingSource;
}
```

### Evaluating the three approaches

- **Form1** just does not work
- **Form2** we need to *touch* the DataGridView once loaded to get at loaded data
- **Form3** Set the DataGridView.DataSource and no need to *touch* the DataGridView once loaded to access data.
- Check out :point_right: `ChangeTracker.DebugView.LongView`

# Evaluating local changes

In DataOperations class, Show method provides access to the [State](https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.entitystate?view=efcore-5.0) of each record.

```csharp
public static string Show()
{
StringBuilder builder = new ();
foreach (var person in Context.Person.Local)
{
if (Context.Entry(person).State != EntityState.Unchanged)
{
builder.AppendLine($"{person.Id} {person.FirstName} {person.LastName} {Context.Entry(person).State}");
}
}

return builder.ToString();
}
```

# Lessons learned

What can be learned is not to work directly with a DataGridView for displaying database data using EF Core 5 or higher.

Novice developers tend to want the easiest way to code a solution which is great while when they don�t understand and/or think ahead will a) write a good deal more code then required b) seek help and in many cases unwilling to accept, in this case using a BindingList with a BindingSource.

So looking at the `big picture` past working with a DataGridView and EF Core is to think ahead for other coding task. Even better, take time when appropriate after reading documentation write unit test to validate that what you think the code should do actually does.

# Running code

- **Requires**
- Visual Studio 2019 or higher
- SQL-Server Express edition or higher
- Run createPersonTable.sql script
- In Program.cs, set the startup form to Form1, run, try Form2, run the Form3 and run

# See also

- Microsoft TechNet Wiki
- [Motivation for moving to Entity Framework Core (C#)](https://social.technet.microsoft.com/wiki/contents/articles/53996.motivation-for-moving-to-entity-framework-core-c.aspx)
- [Entity Framework: Disconnected Entities](https://social.technet.microsoft.com/wiki/contents/articles/53180.entity-framework-disconnected-entities.aspx)
- [Entity Framework Windows Form validation](https://social.technet.microsoft.com/wiki/contents/articles/53201.entity-framework-windows-form-validation.aspx)
- [Entity Framework Core 3: projections](https://social.technet.microsoft.com/wiki/contents/articles/53881.entity-framework-core-3-projections.aspx) (valid with newer releases)
- Microsoft documentation
- [Change Tracking in EF Core](https://docs.microsoft.com/en-us/ef/core/change-tracking/)
- [Testing code that uses EF Core](https://docs.microsoft.com/en-us/ef/core/testing/)

# Edit

Added `Form4` to respond to a form question.