当前位置:Gxlcms > 数据库问题 > UWP: 在 UWP 中使用 Entity Framework Core 操作 SQLite 数据库

UWP: 在 UWP 中使用 Entity Framework Core 操作 SQLite 数据库

时间:2021-07-01 10:21:17 帮助过:6人阅读

-Package Microsoft.EntityFrameworkCore.Tools

其中,第一个是 EF Core 库本身,而二个提供了用于 Migration 的工具。

这里简单解释一下 Migration(一译,迁移),它以增量的方式来修改数据库以及表结构,使 EF Core 的模型与数据库保持一致,并且不会影响数据库中现有的数据。

接下来,在 LSNote.Model 项目中,添加以下代码,其中包括三个类:

using Microsoft.EntityFrameworkCore;

namespace LSNote.Model
{
    public class Note
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public Category Category { get; set; }
    }

    public class Category
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class NoteDbContext : DbContext
    {
        public DbSet<Category> Categories { get; set; }

        /// <summary>
        /// 数据库文件的路径
        /// </summary>
        public string DbFilePath { get; set; }

        public DbSet<Note> Notes { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);

            // 设置数据库文件的路径
            optionsBuilder.UseSqlite($"Data Source={DbFilePath}");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // 必填
            modelBuilder.Entity<Category>().Property(m => m.Name).IsRequired();
            modelBuilder.Entity<Note>().Property(m => m.Title).IsRequired();
        }
    }
}

其中:

  • Note:表示一个笔记项;
  • Category: 表示一个类别,即笔记的类别;
  • NoteDbContext: 这个类继承自 DbContext,它里面包括了若干了 DbSet<T> 的属性,代表对应的数据表;

此外在 NoteDbContext 中,我们重载的两个方法意义分别如下:

  • OnConfiguring: 配置数据库,每当 DbContext 实例被创建时,它都会被执行;
  • OnModelCreating: 配置 Model 及其属性,并最终影响数据表以及字段;

然后,为了使用 Migration,我们还要编辑 LSNote.Model 项目的属性(编辑 LSNote.Model.csproj):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netcoreapp2.0;netstandard2.0</TargetFrameworks>  
    <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="microsoft.entityframeworkcore.sqlite" Version="2.0.1" />
    <PackageReference Include="microsoft.entityframeworkcore.tools" Version="2.0.1" />
  </ItemGroup>
</Project>

注意其中增加的加粗部分,我们使当前项目的目标框架为 .netcoreapp2.0 和 .netstandard2.0,另外增加了 GenerateRuntimeConfigurationFiles 节点。

此时,设置 LSNote.Model 为启动项目,然后在 PMC(Package Manager Console)中,确保 Defalut project 也是 LSNote.Model,之后,输入以下命令:

Add-Migration Init

其中 Init 是本次 Migration 的名称。之后,可以看到在项目中生成了一个 Migrations 文件夹,其下包括了代表每次 Migration 的类文件,它们继承自 Migration 类,如下:

技术分享图片

注意:执行 Migration 命令,必须使 LSNote.Model 项目为启动项,这是因为目前版本的 EF Core Tools 还不支持 UWP 这种类型的项目。

3. 在 UWP 项目中使用

首先,为 UWP 项目也添加对 EF Core 的引用,执行命令:

Install-Package Microsoft.EntityFrameworkCore.Sqlite

接下来,在 App.xaml.cs 文件中,增加以下代码(加粗部分):

using Microsoft.EntityFrameworkCore;

        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;

            DbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "notes.db");

            try
            {
                using (var con = new LSNote.Model.NoteDbContext())
                {
                    con.DbFilePath = DbPath;

                    con.Database.Migrate();
                }
            }
            catch (NotSupportedException ex)
            {
            }
            catch (Exception ex)
            {
            }
        }

        public static string DbPath { get; set; }

通过 DatabaseFacade 类的 Migrate 方法,将挂起的 Migration 应用到数据库,如果数据库还没创建,它会先创建数据库;其中 DatabaseFacade 类由 con.Database 属性得到。

然后,我们在 MainPage.xaml.cs 中,添加以下代码:

    public sealed partial class MainPage : Page, INotifyPropertyChanged
    {
        private List<Note> _allNotes;

        public MainPage()
        {
            this.InitializeComponent();

            this.Loaded += MainPage_Loaded;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public List<Note> AllNotes
        {
            get { return _allNotes; }
            set
            {
                _allNotes = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AllNotes)));
            }
        }

        private void MainPage_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
        {
            using (var con = new NoteDbContext())
            {
                // 设置数据库路径
                con.DbFilePath = App.DbPath;

                // 添加分类
                if (con.Categories.ToList().Count == 0)
                {
                    var cate1 = new Category { Name = "分类A" };
                    var cate2 = new Category { Name = "分类B" };
                    con.Categories.AddRange(cate1, cate2);
                    con.SaveChanges();
                }

                // 添加笔记
                con.Notes.Add(new Note { Title = "这是一条记录", Content = "一些备注", Category = con.Categories.First() });
                con.SaveChanges();

                // 查询
                AllNotes = con.Notes.ToList();
            }
        }
    }

在 MainPage.xaml 中添加以下代码:

<Page
    ...
    xmlns:model="using:LSNote.Model"
    ...

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView x:Name="list" ItemsSource="{x:Bind AllNotes, Mode=OneWay}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="model:Note">
                    <StackPanel Margin="0,4">
                        <TextBlock
                            FontSize="16"
                            FontWeight="SemiBold"
                            Text="{x:Bind Title}" />
                        <TextBlock Text="{x:Bind Content}" />
                        <TextBlock>
                            <Run Text="Category:" />
                            <Run Text="{x:Bind Category.Name}" />
                        </TextBlock>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

这时,将 UWP 项目设置为启动项目,按 F5 运行,即可看到结果:

技术分享图片

4. 进一步使用 Migration

前面说过,使用 EF Core,我们可以使用它自身的特性,例如,当我们要对现有的数据库或表结构修改时,使用 Migration 将会非常简单。对于上面的 Note 实体,我们要为它新添加一个 IsDelete 属性,然后再通过 Add-Migration 命令和 Migrate 方法最终影响到数据库。

首先,添加属性:

    public bool IsDelete { get; set; }

接下来,仍然要设置 LSNote.Model 为启动项目,并且在 PMC 中确认 Defalut project 也是它,输入命令:

Add-Migration AddIsDeleteField

这时,在 Migrations 文件夹会新生成对应的类文件。

切换启动项目为 UWP 项目,并且在 MainPage.xaml 中增加以下代码(加粗部分):

    <DataTemplate x:DataType="model:Note">
        <StackPanel Margin="0,4">
            <TextBlock
                FontSize="16"
                FontWeight="SemiBold"
                Text="{x:Bind Title}" />
            <TextBlock Text="{x:Bind Content}" />
            <TextBlock>
                <Run Text="Category:" />
                <Run Text="{x:Bind Category.Name}" />
            </TextBlock>
            <TextBlock>
                <Run Text="IsDelete:" />
                <Run Text="{x:Bind IsDelete}" />
            </TextBlock>
        </StackPanel>
    </DataTemplate>

按 F5 运行,即可看到更新后的结果:

技术分享图片

补充的话:关于 Migration

  • 对于 SQLite,EF Core 的 Migration 目前还有一些限制,并不能满足所有的功能,如在创建数据表后,再添加外键、添加主键,等。这里有一份完整的限制操作列表;如果在 Migration 中,包括这些操作,将会引发 NotSupportedException。不过,值得注意的是,随着 EF Core 的不断完善,在将来,这些限制都应该会一一实现;
  • 另外,建议每次在 Migration 前要备份数据

总结

本文主要讨论了在 UWP 中如何使用 EF Core,由于两者都依赖并且支持 .NET Standard 2.0,所以在 EF Core 能够被用于 UWP 中,并且运行在任何支持 Win 10 的设备上。接下来,如果你正在开发或者准备开发的应用会用到 SQLite 数据库,不妨试试 EF Core 。

 

参考资料:

Getting Started with EF Core on Universal Windows Platform

The Secret to Running EF Core 2.0 Migrations from a NET Core or NET Standard Class Library

 

源码下载

UWP: 在 UWP 中使用 Entity Framework Core 操作 SQLite 数据库

标签:port   tab   start   sso   wpf   with   UI   data-   initial   

人气教程排行