Note: this article is published on 04/21/2021.
After I wrote several articles on this site, I found out it seemed almost for every article, I needed to set up a sample application associated with an entity framework if accessing the database. And, every time, I needed to rewrite the setup process from scratch in order for a new reader to follow along easily. Even for introducing a very simple concept, such as Caching, I needed to spend 80% of the time setting up the sample app, and only 20% on introducing the Caching concept itself.
Therefore, I think it is better to write a basic model such as entity framework sample for various approaches, and then I can reuse them when needed. I made a list of the series of articles below, I will write them one by one, while the Entity framework overview and concept will be covered in the article (0):
- Entity Framework (0), Overview
- Entity Framework (1), with .Net MVC, Code-First
- Entity Framework (2), with .Net MVC, Database-First
- Entity Framework (3), with .Net MVC, Model-First
- Entity Framework (4), with .Net Core MVC, Code-First
- Entity Framework (5), with .Net Core MVC, Database-First
- Entity Framework (6), with .Net Core MVC, Model-First
- Entity Framework (7), with .Net WPF, Database-First --- this article
- Entity Framework (8), with .NET Core Web API, Stored Procedure
- Entity Framework (9), with .NET Core Web API, Stored Procedure Implementation
- Entity Framework (10), with .Net WebForms, Database-First
- Entity Framework (11), with .Net Core Razor Pages Code-First
- Entity Framework (12), with New .Net Core MVC Code-First
- Entity Framework (13), with .Net Core Code-First Summary
Note
We write the Entity Framework for WPF app, but the pattern is the same or similar when applying to Web Application, we just emphasize the major difference here.
Introduction
This article is about Entity Framework with .Net WPF, Database-First approach. We will make a sample app step by step,
- Step 1: Create an ASP.NET WPF application
- Step 2: Reverse Engineer Model
- Step 2-1, Alternative Approach: Code First
- Step 3: Data Binding
- Step 4: CURD
At the end, we will have a .Net WPF app that can consume a database directly through entity framework.
Step 1 - Create an ASP.NET WPF app
We use the current version of Visual Studio 2019 16.9.3 and .NET Framework 4.8 to build the app:
- Start Visual Studio and select Create a new project.
- In the Create a new project dialog, select WPF App (.NET Framework) > Next.
- In the Configure your new project dialog, enter WPF_DatabaseFirst for Project name > Create.
Build and run the app, it will be an empty window.
Step 2, Reverse Engineer Model
For this step, whatever WPF or Web app (MVC or Web API or Web Forms), they are all the exactly same. We will skip the procedure and use the result at Step 2, from Article Entity Framework (2), with .Net MVC, Database-First,
Once the reverse engineer process completes the new model is added to the project and opened up for viewing in the Entity Framework Designer:
The created entity class, the entity context and the connection string will be exactly the same as ones in the MVC module, where the Store class is like this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace WPF_DatabaseFirst
{
using System;
using System.Collections.Generic;
public partial class store
{
public string stor_id { get; set; }
public string stor_name { get; set; }
public string stor_address { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zip { get; set; }
}
}
the Data Context will be in pubsEntities class:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace WPF_DatabaseFirst
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class pubsEntities : DbContext
{
public pubsEntities()
: base("name=pubsEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<store> stores { get; set; }
}
}
and the connection details for the database will be inserted into app.config file,
<connectionStrings>
<add name="pubsEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=localhost;initial catalog=pubs;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
Step 2-1, Alternative Approach: Code First
In fact, the Code First approach for .NET Framework is quite simple, just using the entity class and context as created above, even the connection string is not necessary, as simple as these,
Entity class
namespace WPF_CodeFirst
{
public partial class store
{
public string stor_id { get; set; }
public string stor_name { get; set; }
public string stor_address { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zip { get; set; }
}
}
Context class
namespace WPF_CodeFirst
{
using System.Data.Entity;
public partial class pubsEntities : DbContext
{
public virtual DbSet<store> stores { get; set; }
}
}
build the app, we have the database created automatically. See details from Article Entity Framework (1), with .Net MVC, Code-First,
Step 3 - Data Binding: Build the Grid, and Run the app
From both and either the Database First approach or Code First approach above, we got here for the next step: Data Binding, which is something of WPF different from Web module where we can use Scaffolder tool to build the CRUD (controller) using entity framework automatically.
In fact, for the Visual Studio 2010, our job has been almost done, as I described in my previous article WCF (4), RIA Services, that gave a entity database first approach for building a WPF app:
- We already have a DataSource available for Data Binding:
- Drag and Drop DataSource into XAML window
- Run the app, we got the Data Grid
However, for current Visual Studio, actually, after VS 2010, we need to do a little bit more work:
1, Build a Data Source Object:
-
From the main menu, select Project => Add New Data Source … (in Visual Studio 2010, select Data => Add New Data Source…)
-
In the Choose a Data Source Type window, select Object and click Next
-
In the Select the Data Objects dialog, unfold the application name, here: WPF_DatabaseFirst two times and select data Store => Finish
- Now we have the Data Source (open: VS Main menu => View => Other Windows => Data Sources):
2, Build a Grid and link to Data Source:
- Drag and Drop DataSource into XAML window, however, we still cannot see the data after running the app:
This is because after dragging and dropping Data Source into Window, the window code behind does not really setup the connection to the data source as VS 2010 did,
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Data.CollectionViewSource storeViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("storeViewSource")));
// Load data by setting the CollectionViewSource.Source property:
// storeViewSource.Source = [generic data source]
}
}
Create a Context instance, and link the DataView Source to the Data Source:
public partial class MainWindow : Window
{
private pubsEntities _context = new pubsEntities();
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Data.CollectionViewSource storeViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("storeViewSource")));
_context.stores.Load();
//Load data by setting the CollectionViewSource.Source property:
// storeViewSource.Source = [generic data source]
storeViewSource.Source = _context.stores.Local;
}
}
Now we have the result we want,
Step 4 - CURD
For Web app, after building entity framework, we can use Scaffolder to make CURD happen in controller. Now, we can view data, we need to add CUD:
Actually, add a save button in the Window, we can do the job:
- From the Toolbox, drag Button on to the form. Set the Content property to Save:
- Double Click the button, then add logic into the event handler:
private void button_Click_1(object sender, RoutedEventArgs e)
{
// all changes are automatically tracked, including
// deletes!
_context.SaveChanges();
// this forces the grid to refresh to latest values
storeDataGrid.Items.Refresh();
//productsDataGrid.Items.Refresh();
}
The Save button will do the CUD work:
Summary
The .NET WPF for Database-First approach is much similar to the web app, with a little bit more work. Here, we just discuss the basic concept to use Entity Framework to build a simple data driven app and see the similarity with Web apps, but we did not touch more complex issue for WPF exclusively. For example, for master/details data, the database first approach need to modify the auto created code, such as using ObservableCollection, instead of ICollection, see here for details. And we did not touch the major features for WPF, such as enforcing INotifyPropertyChanged interface to notice any data changes, The project did this by manually calling Refresh()
.
Reference