在通用 Windows 平台 (UWP) 上使用 EF Core 搭配新資料庫的使用者入門Getting Started with EF Core on Universal Windows Platform (UWP) with a New Database

注意

本教學課程使用 EF Core 2.0.1 (連同 ASP.NET Core 和 .NET Core SDK 2.0.3 一起發行)。This tutorial uses EF Core 2.0.1 (released alongside ASP.NET Core and .NET Core SDK 2.0.3). EF Core 2.0.0 缺少良好 UWP 體驗所需的某些重要錯誤 (bug) 修正。EF Core 2.0.0 lacks some crucial bug fixes required for a good UWP experience.

在本逐步解說中,您將建置通用 Windows 平台 (UWP) 應用程式,該應用程式將使用 Entity Framework 對本機 SQLite 資料庫執行基本資料存取。In this walkthrough, you will build a Universal Windows Platform (UWP) application that performs basic data access against a local SQLite database using Entity Framework.

重要

請考慮避免在 UWP 上的 LINQ 查詢中使用匿名型別Consider avoiding anonymous types in LINQ queries on UWP. 若要將 UWP 應用程式部署至應用程式市集,您的應用程式需要使用 .NET Native 來編譯。Deploying a UWP application to the app store requires your application to be compiled with .NET Native. 使用匿名型別的查詢在 .NET Native 上會有較差的效能。Queries with anonymous types have worse performance on .NET Native.

提示

您可以在 GitHub 上檢視此文章的範例 (英文)。You can view this article's sample on GitHub.

必要條件Prerequisites

若要完成此逐步解說,必須要有下列項目:The following items are required to complete this walkthrough:

建立新模型專案Create a new model project

警告

由於 .NET Core 工具與 UWP 專案互動方式的限制,模型需要放置在非 UWP 專案中,才能在套件管理員主控台中執行移轉命令Due to limitations in the way .NET Core tools interact with UWP projects the model needs to be placed in a non-UWP project to be able to run migrations commands in the Package Manager Console

  • 開啟 Visual StudioOpen Visual Studio

  • [檔案] > [新增] > [專案]...File > New > Project...

  • 從左側功能表選取 [範本] > [Visual C#]From the left menu select Templates > Visual C#

  • 選取 [類別庫 (.NET Standard)] 專案範本Select the Class Library (.NET Standard) project template

  • 提供專案名稱,然後按一下 [確定]Give the project a name and click OK

安裝 Entity FrameworkInstall Entity Framework

若要使用 EF Core,請針對您要作為目標的資料庫提供者來安裝套件。To use EF Core, install the package for the database provider(s) you want to target. 本逐步解說使用 SQLite。This walkthrough uses SQLite. 如需可用的提供者清單,請參閱資料庫提供者For a list of available providers see Database Providers.

  • [工具] > [NuGet 套件管理員] > [套件管理員主控台]Tools > NuGet Package Manager > Package Manager Console

  • 執行 Install-Package Microsoft.EntityFrameworkCore.SqliteRun Install-Package Microsoft.EntityFrameworkCore.Sqlite

稍後在本逐步解說中,我們將使用部分 Entity Framework 工具來維護資料庫。Later in this walkthrough we will also be using some Entity Framework Tools to maintain the database. 因此,我們也將安裝工具套件。So we will install the tools package as well.

  • 執行 Install-Package Microsoft.EntityFrameworkCore.ToolsRun Install-Package Microsoft.EntityFrameworkCore.Tools

  • 編輯 .csproj 檔案,並以 <TargetFrameworks>netcoreapp2.0;netstandard2.0</TargetFrameworks> 取代 <TargetFramework>netstandard2.0</TargetFramework>Edit the .csproj file and replace <TargetFramework>netstandard2.0</TargetFramework> with <TargetFrameworks>netcoreapp2.0;netstandard2.0</TargetFrameworks>

建立您的模型Create your model

現在就來定義組成模型的內容和實體類別。Now it's time to define a context and entity classes that make up your model.

  • [專案] > [加入類別]...Project > Add Class...

  • 輸入 Model.cs 作為名稱,然後按一下 [確定]Enter Model.cs as the name and click OK

  • 以下列程式碼來取代檔案的內容Replace the contents of the file with the following code

using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;

namespace EFGetStarted.UWP
{
    public class BloggingContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite("Data Source=blogging.db");
        }
    }

    public class Blog
    {
        public int BlogId { get; set; }
        public string Url { get; set; }

        public List<Post> Posts { get; set; }
    }

    public class Post
    {
        public int PostId { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }

        public int BlogId { get; set; }
        public Blog Blog { get; set; }
    }
}

建立新 UWP 專案Create a new UWP project

  • 開啟 Visual StudioOpen Visual Studio

  • [檔案] > [新增] > [專案]...File > New > Project...

  • 從左側功能表選取 [範本] > [Visual C#] > [Windows 通用]From the left menu select Templates > Visual C# > Windows Universal

  • 選取 [空白應用程式 (通用 Windows)] 專案範本Select the Blank App (Universal Windows) project template

  • 提供專案名稱,然後按一下 [確定]Give the project a name and click OK

  • 將目標和最小版本至少設定為 Windows 10 Fall Creators Update (10.0; build 16299.0)Set the target and minimum versions to at least Windows 10 Fall Creators Update (10.0; build 16299.0)

建立您的資料庫Create your database

一旦有模型之後,就可以使用移轉來建立資料庫。Now that you have a model, you can use migrations to create a database for you.

  • [工具] –> [NuGet 套件管理員] –> [套件管理員主控台]Tools –> NuGet Package Manager –> Package Manager Console

  • 選取模型專案作為預設專案,並將它設定為啟始專案Select the model project as the Default project and set it as the startup project

  • 執行 Add-Migration MyFirstMigration 來建立移轉的結構,以針對您的模型建立一組初始的資料表。Run Add-Migration MyFirstMigration to scaffold a migration to create the initial set of tables for your model.

因為我們要在執行應用程式的裝置上建立資料庫,所以我們將加入一些程式碼,在應用程式啟動時將任何擱置中的移轉套用至本機資料庫。Since we want the database to be created on the device that the app runs on, we will add some code to apply any pending migrations to the local database on application startup. 第一次執行應用程式時,這會負責為我們建立本機資料庫。The first time that the app runs, this will take care of creating the local database for us.

  • 在 [方案總管] 中,以滑鼠右鍵按一下 [App.xaml],然後選取 [檢視程式碼]Right-click on App.xaml in Solution Explorer and select View Code

  • 將醒目提示的 using 加入檔案的開頭Add the highlighted using to the start of the file

  • 加入醒目提示的程式碼,以套用擱置中的移轉Add the highlighted code to apply any pending migrations

using Microsoft.EntityFrameworkCore;
using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace EFGetStarted.UWP
{
    /// <summary>
    /// Provides application-specific behavior to supplement the default Application class.
    /// </summary>
    sealed partial class App : Application
    {
        /// <summary>
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// </summary>
        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;

            using (var db = new BloggingContext())
            {
                db.Database.Migrate();
            }
        }

        /// <summary>
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// </summary>
        /// <param name="e">Details about the launch request and process.</param>
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
#if DEBUG
            if (System.Diagnostics.Debugger.IsAttached)
            {
                this.DebugSettings.EnableFrameRateCounter = true;
            }
#endif
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.NavigationFailed += OnNavigationFailed;

                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (e.PrelaunchActivated == false)
            {
                if (rootFrame.Content == null)
                {
                    // When the navigation stack isn't restored navigate to the first page,
                    // configuring the new page by passing required information as a navigation
                    // parameter
                    rootFrame.Navigate(typeof(MainPage), e.Arguments);
                }
                // Ensure the current window is active
                Window.Current.Activate();
            }
        }

        /// <summary>
        /// Invoked when Navigation to a certain page fails
        /// </summary>
        /// <param name="sender">The Frame which failed navigation</param>
        /// <param name="e">Details about the navigation failure</param>
        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
        }

        /// <summary>
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// </summary>
        /// <param name="sender">The source of the suspend request.</param>
        /// <param name="e">Details about the suspend request.</param>
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            deferral.Complete();
        }
    }
}

提示

如果日後要對您的模型進行變更,則可以使用 Add-Migration 命令來建立新移轉的結構,以將相對應的變更套用至資料庫。If you make future changes to your model, you can use the Add-Migration command to scaffold a new migration to apply the corresponding changes to the database. 應用程式啟動時,會將任何擱置中的移轉套用至每個裝置上的本機資料庫。Any pending migrations will be applied to the local database on each device when the application starts.

EF 在資料庫中使用 __EFMigrationsHistory 資料表,以確認已經套用至資料庫的移轉。EF uses a __EFMigrationsHistory table in the database to keep track of which migrations have already been applied to the database.

使用您的模型Use your model

您現在可以使用您的模型來執行資料存取。You can now use your model to perform data access.

  • 開啟 MainPage.xamlOpen MainPage.xaml

  • 加入下列醒目提示的頁面載入處理常式和 UI 內容Add the page load handler and UI content highlighted below

<Page
    x:Class="EFGetStarted.UWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:EFGetStarted.UWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Loaded="Page_Loaded">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <TextBox Name="NewBlogUrl"></TextBox>
            <Button Click="Add_Click">Add</Button>
            <ListView Name="Blogs">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Url}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackPanel>
    </Grid>
</Page>

現在我們將加入程式碼,以連接 UI 與資料庫Now we'll add code to wire up the UI with the database

  • 在 [方案總管] 中,以滑鼠右鍵按一下 [MainPage.xaml],然後選取 [檢視程式碼]Right-click MainPage.xaml in Solution Explorer and select View Code

  • 從下列清單中加入醒目提示的程式碼Add the highlighted code from the following listing

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace EFGetStarted.UWP
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            using (var db = new BloggingContext())
            {
                Blogs.ItemsSource = db.Blogs.ToList();
            }
        }

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            using (var db = new BloggingContext())
            {
                var blog = new Blog { Url = NewBlogUrl.Text };
                db.Blogs.Add(blog);
                db.SaveChanges();

                Blogs.ItemsSource = db.Blogs.ToList();
            }
        }
    }
}

您現在可以執行應用程式來查看運作狀況。You can now run the application to see it in action.

  • 偵錯 > 啟動但不偵錯Debug > Start Without Debugging

  • 系統將會建置並啟動應用程式The application will build and launch

  • 輸入 URL 並按一下 [加入] 按鈕Enter a URL and click the Add button

image

image

後續步驟Next steps

提示

在您的實體類型中實作 INotifyPropertyChangedINotifyPropertyChangingINotifyCollectionChanged 和使用 ChangeTrackingStrategy.ChangingAndChangedNotifications,可以改善 SaveChanges() 的效能。SaveChanges() performance can be improved by implementing INotifyPropertyChanged, INotifyPropertyChanging, INotifyCollectionChanged in your entity types and using ChangeTrackingStrategy.ChangingAndChangedNotifications.

大功告成!Tada! 您現在有一個執行 Entity Framework 的簡單 UWP 應用程式了。You now have a simple UWP app running Entity Framework.

請參閱此文件中的其他文章,以深入了解 Entity Framework 的功能。Check out other articles in this documentation to learn more about Entity Framework's features.