DataGridView/Entity Framework common operations (Part 2)
Introduction
This is a continuation of part 1 in this series which should be read before continuing with this part of the series if new to working with Entity Framework in Window Form projects.
Here the lesson to having a DataGridView populated with data read from a main table, customers along with related tables for contact, contact type and country which provides immediate updating capabilities when editing cells which mimics the behavior found when working with Microsoft Access data.
Unlike working with conventional DataSet and DataTable containers there is more work involved and by following along with this article and included code samples the logic needed to provide the same functionality will become easy to implement in any project.
Base classes for reading data
Since this demonstration works with a main table and several related tables a special class is needed to provide properties to display in the related tables as the main table for instance for contact only has the primary key of the customer and this goes for country and contact type.
Below shows relationships, note for Countries the primary key id is setup as a read-only property were another way to handle this is by using property mapping.
Figure 1
To provide notification of data changing in the DataGridView this class which implements INotifyPropertyChanged Interface.
Imports System.ComponentModel
Imports System.ComponentModel.DataAnnotations
Imports System.Runtime.CompilerServices
Public Class CustomerEntity
Inherits BaseEntity
Implements INotifyPropertyChanged
Private _customerIdentifier1 As Integer
Private _companyName1 As String
Private _contactIdentifier1 As Integer?
Private _firstName1 As String
Private _lastName1 As String
Private _contactTypeIdentifier1 As Integer
Private _contactTitle1 As String
Private _address1 As String
Private _city1 As String
Private _postalCode1 As String
Private _countryIdentifier1 As Integer?
Private _countyName1 As String
Public Property CustomerIdentifier() As Integer
Get
Return _customerIdentifier1
End Get
Set
_customerIdentifier1 = Value
OnPropertyChanged()
End Set
End Property
<Required>
Public Property CompanyName() As String
Get
Return _companyName1
End Get
Set
_companyName1 = Value
OnPropertyChanged()
End Set
End Property
Public Property ContactIdentifier() As Integer?
Get
Return _contactIdentifier1
End Get
Set
_contactIdentifier1 = Value
OnPropertyChanged()
End Set
End Property
Public Property FirstName() As String
Get
Return _firstName1
End Get
Set
_firstName1 = Value
OnPropertyChanged()
End Set
End Property
Public Property LastName() As String
Get
Return _lastName1
End Get
Set
_lastName1 = Value
OnPropertyChanged()
End Set
End Property
Public ReadOnly Property ContactName() As String
Get
Return $"{FirstName} {LastName}"
End Get
End Property
Public Property ContactTypeIdentifier() As Integer
Get
Return _contactTypeIdentifier1
End Get
Set
_contactTypeIdentifier1 = Value
OnPropertyChanged()
End Set
End Property
Public Property ContactTitle() As String
Get
Return _contactTitle1
End Get
Set
_contactTitle1 = Value
OnPropertyChanged()
End Set
End Property
Public Property Street() As String
Get
Return _address1
End Get
Set
_address1 = Value
OnPropertyChanged()
End Set
End Property
Public Property City() As String
Get
Return _city1
End Get
Set
_city1 = Value
OnPropertyChanged()
End Set
End Property
Public Property PostalCode() As String
Get
Return _postalCode1
End Get
Set
_postalCode1 = Value
OnPropertyChanged()
End Set
End Property
Public Property CountryIdentifier() As Integer?
Get
Return _countryIdentifier1
End Get
Set
_countryIdentifier1 = Value
OnPropertyChanged()
End Set
End Property
Public Property CountryName() As String
Get
Return _countyName1
End Get
Set
_countyName1 = Value
OnPropertyChanged()
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler _
Implements INotifyPropertyChanged.PropertyChanged
Protected Overridable Sub OnPropertyChanged(
<CallerMemberName> Optional memberName As String = Nothing)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(memberName))
End Sub
End Class
In turn the CustomerEntity class is used in the following static property to retrieve customer and related data from the database.
Imports System.ComponentModel.DataAnnotations.Schema
Imports System.Linq.Expressions
Partial Public Class Customer
<NotMapped>
Public Property FirstName As String
<NotMapped>
Public Property LastName As String
Public Shared ReadOnly Property Projection() As Expression(Of Func(Of Customer, CustomerEntity))
Get
Return Function(customer) New CustomerEntity() With {
.CustomerIdentifier = customer.CustomerIdentifier,
.CompanyName = customer.CompanyName,
.Street = customer.Street,
.City = customer.City,
.PostalCode = customer.PostalCode,
.ContactTypeIdentifier = customer.ContactTypeIdentifier.Value,
.ContactTitle = customer.ContactType.ContactTitle,
.CountryName = customer.Country.CountryName,
.FirstName = customer.Contact.FirstName,
.LastName = customer.Contact.LastName,
.ContactIdentifier = CInt(customer.ContactIdentifier),
.CountryIdentifier = customer.CountryIdentifier}
End Get
End Property
End Class
In the form the following method reads in data asynchronously. Note when working with a large amount of rows and columns of data this allows the user interface to remain responsive.
Public Async Function AllCustomersAsync() As Task(Of List(Of CustomerEntity))
Return Await Task.Run(
Async Function()
Dim customerItemsList As List(Of CustomerEntity) =
Await Context.Customers.Select(Customer.Projection).ToListAsync()
Return customerItemsList.OrderBy(Function(customer) customer.CompanyName).ToList()
End Function)
End Function
Setup
- Create the database in SQL-Server using the following script Jump .
- Clone the repository.
- Do a restore NuGet packages
- Build and run the project the front end project Jump which uses this back end project Jump .
Summary
In this part of the series loading data into a DataGridView with functionality to perform immediate updates have been shown. In the next part of this series adding new data and removing current data will be shown along with various ways to filter data.
See also
VB.NET Entity Framework: Wiki portal
DataGridView/Entity Framework common operations (Part 1)
DataGridView/Entity Framework common operations (Part 2 A)