Skip to content

Commit

Permalink
Merge pull request #2553 from dotnet/master
Browse files Browse the repository at this point in the history
Publish 8/3/20
  • Loading branch information
smitpatel committed Aug 3, 2020
2 parents 5114892 + 0057abc commit 949faab
Show file tree
Hide file tree
Showing 40 changed files with 438 additions and 40 deletions.
2 changes: 1 addition & 1 deletion entity-framework/core/extensions/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ An ORM that creates strongly-typed, extendable classes for Entity Framework. The

### EF Core Power Tools

EF Core Power Tools is a Visual Studio extension that exposes various EF Core design-time tasks in a simple user interface. It includes reverse engineering of DbContext and entity classes from existing databases and [SQL Server DACPACs](https://docs.microsoft.com/sql/relational-databases/data-tier-applications/data-tier-applications), management of database migrations, and model visualizations. For EF Core: 2, 3.
EF Core Power Tools is a Visual Studio extension that exposes various EF Core design-time tasks in a simple user interface. It includes reverse engineering of DbContext and entity classes from existing databases and [SQL Server DACPACs](/sql/relational-databases/data-tier-applications/data-tier-applications), management of database migrations, and model visualizations. For EF Core: 2, 3.

[GitHub wiki](https://github.com/ErikEJ/EFCorePowerTools/wiki)

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
170 changes: 170 additions & 0 deletions entity-framework/core/get-started/wpf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
---
title: "Get Started with WPF - EF Core"
author: jeremylikness
ms.author: jeliknes
ms.date: 07/24/2020
uid: core/get-started/wpf
---
# Getting Started with WPF

This step-by-step walkthrough shows how to bind POCO types to WPF controls in a "main-detail" form. The application uses the Entity Framework APIs to populate objects with data from the database, track changes, and persist data to the database.

The model defines two types that participate in one-to-many relationship: **Category** (principal\\main) and **Product** (dependent\\detail). The WPF data-binding framework enables navigation between related objects: selecting rows in the master view causes the detail view to update with the corresponding child data.

The screen shots and code listings in this walkthrough are taken from Visual Studio 2019 16.6.5.

> [!TIP]
> You can view this article's [sample on GitHub](https://github.com/dotnet/EntityFramework.Docs/tree/master/samples/core/WPF).
## Pre-Requisites

* You need to have Visual Studio 2019 16.3 or later installed with the **.NET desktop workload** selected to complete this walkthrough.

For more information about installing the latest version of Visual Studio, see [Install Visual Studio](/visualstudio/install/install-visual-studio).

## Create the Application

1. Open Visual Studio
2. On the start window, choose **Create new project**.
3. Search for "WPF," choose **WPF App (.NET Core)** and then choose **Next**.
4. At the next screen, give the project a name, for example, **GetStartedWPF**, and choose **Create.**

## Install the Entity Framework NuGet packages

1. Right-click on the solution and choose **Manage NuGet Packages for Solution...**

![Manage NuGet Packages](_static/wpf-tutorial-nuget.jpg)

1. Type `entityframeworkcore.sqlite` in the search box.
1. Select the **Microsoft.EntityFrameworkCore.Sqlite** package.
1. Check the project in the right pane and click **Install**

![Sqlite Package](_static/wpf-tutorial-sqlite.jpg)

1. Repeat the steps to search for `entityframeworkcore.proxies` and install **Microsoft.EntityFrameworkCore.Proxies**.

> [!NOTE]
> When you installed the Sqlite package, it automatically pulled down the related **Microsoft.EntityFrameworkCore** base package. The **Microsoft.EntityFrameworkCore.Proxies** package provides support for "lazy-loading" data. This means when you have entities with child entities, only the parents are fetched on the initial load. The proxies detect when an attempt to access the child entities is made and automatically loads them on demand.
## Define a Model

In this walkthrough you will implement a model using "code first." This means that EF Core will create the database tables and schema based on the C# classes you define.

Add a new class. Give it the name: `Product.cs` and populate it like this:

**`Product.cs`**

[!code-csharp[](../../../samples/core/WPF/GetStartedWPF/GetStartedWPF/Product.cs)]

Next, add a class named `Category.cs` and populate it with the following code:

**`Category.cs`**

[!code-csharp[](../../../samples/core/WPF/GetStartedWPF/GetStartedWPF/Category.cs)]

The **Products** property on the **Category** class and **Category** property on the **Product** class are navigation properties. In Entity Framework, navigation properties provide a way to navigate a relationship between two entity types.

In addition to defining entities, you need to define a class that derives from DbContext and exposes DbSet<TEntity> properties. The DbSet<TEntity> properties let the context know which types you want to include in the model.

An instance of the DbContext derived type manages the entity objects during run time, which includes populating objects with data from a database, change tracking, and persisting data to the database.

Add a new `ProductContext.cs` class to the project with the following definition:

**`ProductContext.cs`**

[!code-csharp[](../../../samples/core/WPF/GetStartedWPF/GetStartedWPF/ProductContext.cs)]

* The `DbSet` informs EF Core what C# entities should be mapped to the database.
* There are a variety of ways to configure the EF Core `DbContext`. You can read about them in: [Configuring a DbContext](/ef/core/miscellaneous/configuring-dbcontext).
* This example uses the `OnConfiguring` override to specify a Sqlite data file.
* The `UseLazyLoadingProxies` call tells EF Core to implement lazy-loading, so child entities are automatically loaded when accessed from the parent.

Press **CTRL+SHIFT+B** or navigate to **Build > Build Solution** to compile the project.

> [!TIP]
> Learn about the different was to keep your database and EF Core models in sync: [Managing Database Schemas](/ef/core/managing-schemas).
## Lazy Loading

The **Products** property on the **Category** class and **Category** property on the **Product** class are navigation properties. In Entity Framework Core, navigation properties provide a way to navigate a relationship between two entity types.

EF Core gives you an option of loading related entities from the database automatically the first time you access the navigation property. With this type of loading (called lazy loading), be aware that the first time you access each navigation property a separate query will be executed against the database if the contents are not already in the context.

When using "Plain Old C# Object" (POCO) entity types, EF Core achieves lazy loading by creating instances of derived proxy types during runtime and then overriding virtual properties in your classes to add the loading hook. To get lazy loading of related objects, you must declare navigation property getters as **public** and **virtual** (**Overridable** in Visual Basic), and your class must not be **sealed** (**NotOverridable** in Visual Basic). When using Database First, navigation properties are automatically made virtual to enable lazy loading.

## Bind Object to Controls

Add the classes that are defined in the model as data sources for this WPF application.

1. Double-click **MainWindow.xaml** in Solution Explorer to open the main form
1. Choose the **XAML** tab to edit the XAML.
1. Immediately after the opening `Window` tag, add the following sources to connect to the EF Core entities.

[!code-xaml[](../../../samples/core/WPF/GetStartedWPF/GetStartedWPF/MainWindow.xaml?range=1-13&highlight=9-13)]

1. This sets up source for the "parent" categories, and second source for the "detail" products.
1. Next, add the following markup to your XAML after the closing `Window.Resources` tag.

[!code-xaml[](../../../samples/core/WPF/GetStartedWPF/GetStartedWPF/MainWindow.xaml?range=15-26)]

1. Note that the `CategoryId` is set to `ReadOnly` because it is assigned by the database and cannot be changed.

## Adding a Details Grid

Now that the grid exists to display categories, the details grid can be added to show products.

**`MainWindow.xaml`**

[!code-xaml[](../../../samples/core/WPF/GetStartedWPF/GetStartedWPF/MainWindow.xaml?range=27-40)]

Finally, add a `Save` button and wire in the click event to `Button_Click`.

[!code-xaml[](../../../samples/core/WPF/GetStartedWPF/GetStartedWPF/MainWindow.xaml?range=41-42)]

Your design view should look like this:

![Screenshot of WPF Designer](_static/wpf-tutorial-designer.jpg)

## Add Code that Handles Data Interaction

It's time to add some event handlers to the main window.

1. In the XAML window, click on the **<Window>** element, to select the main window.
1. In the **Properties** window choose **Events** at the top right, then double-click the text box to right of the **Loaded** label.

![Main Window Properties](_static/wpf-tutorial-loaded.jpg)

This brings you to the code behind for the form, we'll now edit the code to use the `ProductContext` to perform data access. Update the code as shown below.

The code declares a long-running instance of `ProductContext`. The `ProductContext` object is used to query and save data to the database. The `Dispose()` method on the `ProductContext` instance is then called from the overridden `OnClosing` method. The code comments explain what each step does.

**`MainWindow.xaml.cs`**

[!code-csharp[](../../../samples/core/WPF/GetStartedWPF/GetStartedWPF/MainWindow.xaml.cs)]

> [!NOTE]
> The code uses a call to `EnsureCreated()` to build the database on the first run. This is acceptable for demos, but in production apps you should look at [migrations](/ef/core/managing-schemas/migrations/) to manage your schema. The code also executes synchronously because it uses a local SQLite database. For production scenarios that typically involve a remote server, consider using the asynchronous versions of the `Load` and `SaveChanges` methods.
## Test the WPF Application

Compile and run the application by pressing **F5** or choosing **Debug > Start Debugging**. The database should be automatically created with a file named `products.db`. Enter a category name and hit enter, then add products to the lower grid. Click save and watch the grid refresh with the database provided ids. Highlight a row and hit **Delete** to remove the row. The entity will be deleted when you click **Save**.

![Running application](_static/wpf-tutorial-app.jpg)

## Property Change Notification

This example relies on four steps to synchronize the entities with the UI.

1. The initial call `_context.Categories.Load()` loads the categories data.
1. The lazy-loading proxies load the dependent products data.
1. EF Core's built-in change tracking makes the necessary modifications to entities, including insertions and deletions, when `_context.SaveChanges()` is called.
1. The calls to `DataGridView.Items.Refresh()` force a reload with the newly generated ids.

This works for our getting started sample, but you may require additional code for other scenarios. WPF controls render the UI by reading the fields and properties on your entities. When you edit a value in the user interface (UI), that value is passed to your entity. When you change the value of a property directly on your entity, such as loading it from the database, WPF will not immediately reflect the changes in the UI. The rendering engine must be notified of the changes. The project did this by manually calling `Refresh()`. An easy way to automate this notification is by implementing the [INotifyPropertyChanged](/dotnet/api/system.componentmodel.inotifypropertychanged) interface. WPF components will automatically detect the interface and register for change events. The entity is responsible for raising these events.

> [!TIP]
> To learn more about how to handle changes, read: [How to implement property change notification](/dotnet/framework/wpf/data/how-to-implement-property-change-notification).
## Next Steps

Learn more about [Configuring a DbContext](/ef/core/miscellaneous/configuring-dbcontext).
8 changes: 4 additions & 4 deletions entity-framework/core/managing-schemas/migrations/managing.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ migrationBuilder.RenameColumn(
### Adding raw SQL

While renaming a column can be achieved via a built-in API, in many cases that is not possible. For example, we may want to replace existing `FirstName` and `LastColumn` properties with a single, new `FullName` property. The migration generated by EF Core will be the following:
While renaming a column can be achieved via a built-in API, in many cases that is not possible. For example, we may want to replace existing `FirstName` and `LastName` properties with a single, new `FullName` property. The migration generated by EF Core will be the following:

``` csharp
migrationBuilder.DropColumn(
Expand All @@ -103,7 +103,7 @@ migrationBuilder.DropColumn(
table: "Customer");

migrationBuilder.AddColumn<string>(
name: "Name",
name: "FullName",
table: "Customer",
nullable: true);
```
Expand All @@ -112,14 +112,14 @@ As before, this would cause unwanted data loss. To transfer the data from the ol

``` csharp
migrationBuilder.AddColumn<string>(
name: "Name",
name: "FullName",
table: "Customer",
nullable: true);

migrationBuilder.Sql(
@"
UPDATE Customer
SET Name = FirstName + ' ' + LastName;
SET FullName = FirstName + ' ' + LastName;
");

migrationBuilder.DropColumn(
Expand Down
2 changes: 1 addition & 1 deletion entity-framework/core/managing-schemas/scaffolding.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Scaffold-DbContext 'Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook'

If you have an ASP.NET Core project, you can use the `Name=<connection-string>` syntax to read the connection string from configuration.

This works well with the [Secret Manager tool](https://docs.microsoft.com/aspnet/core/security/app-secrets#secret-manager) to keep your database password separate from your codebase.
This works well with the [Secret Manager tool](/aspnet/core/security/app-secrets#secret-manager) to keep your database password separate from your codebase.

```dotnetcli
dotnet user-secrets set ConnectionStrings.Chinook "Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Chinook"
Expand Down
4 changes: 2 additions & 2 deletions entity-framework/core/miscellaneous/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ The Entity Framework Core tools help with design-time development tasks. They're
`DbContext` and entity types by reverse engineering the schema of a database.

* The [EF Core Package Manager Console tools](powershell.md) run in
the [Package Manager Console](https://docs.microsoft.com/nuget/tools/package-manager-console) in Visual Studio.
the [Package Manager Console](/nuget/tools/package-manager-console) in Visual Studio.

* The [EF Core .NET command-line interface (CLI) tools](dotnet.md) are an extension to the cross-platform [.NET Core CLI tools](https://docs.microsoft.com/dotnet/core/tools/). These tools require a .NET Core SDK project (one with `Sdk="Microsoft.NET.Sdk"` or similar in the project file).
* The [EF Core .NET command-line interface (CLI) tools](dotnet.md) are an extension to the cross-platform [.NET Core CLI tools](/dotnet/core/tools/). These tools require a .NET Core SDK project (one with `Sdk="Microsoft.NET.Sdk"` or similar in the project file).

Both tools expose the same functionality. If you're developing in Visual Studio, we recommend using the **Package Manager Console** tools since
they provide a more integrated experience.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ Note that some databases allow the collation to be defined when creating an inde

In .NET, string equality is case-sensitive by default: `s1 == s2` performs an ordinal comparison that requires the strings to be identical. Because the default collation of databases varies, and because it is desirable for simple equality to use indexes, EF Core makes no attempt to translate simple equality to a database case-sensitive operation: C# equality is translated directly to SQL equality, which may or may not be case-sensitive, depending on the specific database in use and its collation configuration.

In addition, .NET provides overloads of [`string.Equals`](https://docs.microsoft.com/dotnet/api/system.string.equals#System_String_Equals_System_String_System_StringComparison_) accepting a [`StringComparison`](https://docs.microsoft.com/dotnet/api/system.stringcomparison) enum, which allows specifying case-sensitivity and culture for the comparison. By design, EF Core refrains from translating these overloads to SQL, and attempting to use them will result in an exception. For one thing, EF Core does know not which case-sensitive or case-insensitive collation should be used. More importantly, applying a collation would in most cases prevent index usage, significantly impacting performance for a very basic and commonly-used .NET construct. To force a query to use case-sensitive or case-insensitive comparison, specify a collation explicitly via `EF.Functions.Collate` as [detailed above](#explicit-collations-and-indexes).
In addition, .NET provides overloads of [`string.Equals`](/dotnet/api/system.string.equals#System_String_Equals_System_String_System_StringComparison_) accepting a [`StringComparison`](/dotnet/api/system.stringcomparison) enum, which allows specifying case-sensitivity and culture for the comparison. By design, EF Core refrains from translating these overloads to SQL, and attempting to use them will result in an exception. For one thing, EF Core does know not which case-sensitive or case-insensitive collation should be used. More importantly, applying a collation would in most cases prevent index usage, significantly impacting performance for a very basic and commonly-used .NET construct. To force a query to use case-sensitive or case-insensitive comparison, specify a collation explicitly via `EF.Functions.Collate` as [detailed above](#explicit-collations-and-indexes).

## Database-specific information

* [SQL Server documentation on collations](https://docs.microsoft.com/sql/relational-databases/collations/collation-and-unicode-support).
* [Microsoft.Data.Sqlite documentation on collations](https://docs.microsoft.com/dotnet/standard/data/sqlite/collation).
* [SQL Server documentation on collations](/sql/relational-databases/collations/collation-and-unicode-support).
* [Microsoft.Data.Sqlite documentation on collations](/dotnet/standard/data/sqlite/collation).
* [PostgreSQL documentation on collations](https://www.postgresql.org/docs/current/collation.html).
* [MySQL documentation on collations](https://dev.mysql.com/doc/refman/en/charset-general.html).
4 changes: 2 additions & 2 deletions entity-framework/core/miscellaneous/configuring-dbcontext.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ Always await EF Core asynchronous methods immediately.

### Implicitly sharing DbContext instances across multiple threads via dependency injection

The [`AddDbContext`](https://docs.microsoft.com/dotnet/api/microsoft.extensions.dependencyinjection.entityframeworkservicecollectionextensions.adddbcontext) extension method registers `DbContext` types with a [scoped lifetime](https://docs.microsoft.com/aspnet/core/fundamentals/dependency-injection#service-lifetimes) by default.
The [`AddDbContext`](/dotnet/api/microsoft.extensions.dependencyinjection.entityframeworkservicecollectionextensions.adddbcontext) extension method registers `DbContext` types with a [scoped lifetime](/aspnet/core/fundamentals/dependency-injection#service-lifetimes) by default.

This is safe from concurrent access issues in most ASP.NET Core applications because there is only one thread executing each client request at a given time, and because each request gets a separate dependency injection scope (and therefore a separate `DbContext` instance). For Blazor Server hosting model, one logical request is used for maintaining the Blazor user circuit, and thus only one scoped DbContext instance is available per user circuit if the default injection scope is used.

Expand All @@ -188,5 +188,5 @@ Using dependency injection, this can be achieved by either registering the conte

## More reading

- Read [Dependency Injection](https://docs.microsoft.com/aspnet/core/fundamentals/dependency-injection) to learn more about using DI.
- Read [Dependency Injection](/aspnet/core/fundamentals/dependency-injection) to learn more about using DI.
- Read [Testing](testing/index.md) for more information.
Loading

0 comments on commit 949faab

Please sign in to comment.