因为我们要做一个数据持久化型的小应用,所以在完成Abp功能的集成后,我们需要做数据库相关的配置工作

配置数据库

在MauiBoilerplate.Core项目中,添加两个实体类:

我们简单的写一个歌曲(song)的实体类

其中包含了歌曲标题(MusicTitle),艺术家(Artist),专辑(Album),时长(Duration)以及发售日期(ReleaseDate)

    public class Song : FullAuditedEntity<long>
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public override long Id { get; set; } public string MusicTitle { get; set; } public string Artist { get; set; } public string Album { get; set; } public TimeSpan Duration { get; set; } public DateTime ReleaseDate { get; set; } }

在MauiBoilerplate.EntityFrameworkCore项目中:将这个类添加至MauiBoilerplateDbContext中

public class MauiBoilerplateDbContext : AbpDbContext
{
//Add DbSet properties for your entities...
public DbSet<Song> Song { get; set; }
}

新建WithDbContextHelper.cs

创建一个静态类WithDbContext,利用Abp的工作单元模式对dbcontext执行操作

    public class WithDbContextHelper
{
public static void WithDbContext<TDbContext>(IIocResolver iocResolver, Action<TDbContext> contextAction)
where TDbContext : DbContext
{
using (var uowManager = iocResolver.ResolveAsDisposable<IUnitOfWorkManager>())
{
using (var uow = uowManager.Object.Begin(TransactionScopeOption.Suppress))
{
var context = uowManager.Object.Current.GetDbContext<TDbContext>(); contextAction(context); uow.Complete();
}
}
} }

[可选]种子数据相关类编写

编写种子数据帮助类SeedHelper.cs,与数据库初始化类InitialDbBuilder,这里将在程序启动时向数据库插入一些种子数据

    public static class SeedHelper
{
public static void SeedHostDb(IIocResolver iocResolver)
{
Helper.WithDbContextHelper.WithDbContext<MauiBoilerplateDbContext>(iocResolver, SeedHostDb);
} public static void SeedHostDb(MauiBoilerplateDbContext context)
{
context.SuppressAutoSetTenantId = true; // Host seed
new InitialDbBuilder(context).Create();
} }

编写MauiBoilerplateEntityFrameworkCoreModule.cs

    [DependsOn(
typeof(MauiBoilerplateCoreModule),
typeof(AbpEntityFrameworkCoreModule))]
public class MauiBoilerplateEntityFrameworkCoreModule : AbpModule
{
public bool SkipDbContextRegistration { get; set; } public bool SkipDbSeed { get; set; } public override void PreInitialize()
{
if (!SkipDbContextRegistration)
{
Configuration.Modules.AbpEfCore().AddDbContext<MauiBoilerplateDbContext>(options =>
{
if (options.ExistingConnection != null)
{
DbContextOptionsConfigurer.Configure(options.DbContextOptions, options.ExistingConnection);
}
else
{
DbContextOptionsConfigurer.Configure(options.DbContextOptions, options.ConnectionString);
}
});
}
}
public override void Initialize()
{ IocManager.RegisterAssemblyByConvention(typeof(MauiBoilerplateEntityFrameworkCoreModule).GetAssembly()); } public override void PostInitialize()
{
Helper.WithDbContextHelper.WithDbContext<MauiBoilerplateDbContext>(IocManager, RunMigrate);
if (!SkipDbSeed)
{
SeedHelper.SeedHostDb(IocManager);
}
} public static void RunMigrate(MauiBoilerplateDbContext dbContext)
{
dbContext.Database.Migrate();
} }

将MauiBoilerplate.EntityFrameworkCore设置为启动项目,选择框架为.net6.0

打开程序包管理器控制台,选择默认项目MauiBoilerplate.EntityFrameworkCore

​编辑

运行Add-Migration命令,将生成迁移脚本

运行MauiBoilerplate.EntityFrameworkCore,将生成mato.db等三个文件,

​编辑

编写基类(可选)

我们在使用相关的父类时,某某ContentPage,或者某某UserControl时,需要像使用AbpServiceBase一样使用一些常用的功能,比如字符串的本地化,配置,AutoMapper对象等,就像AbpServiceBase的注释里描述的那样:

/// <summary>

    /// This class can be used as a base class for services.

    /// It has some useful objects property-injected and has some basic methods

    /// most of services may need to.

    /// </summary>

此时,需要编写一个基类(奈何.net本身没有Mixin模式,C#语言也不支持多继承),这些基类仅是注入了一些常用的Manager,方便代码编写者使用,因此基类的创建不是必须的。

比如可以增加一个ContentPageBase类作为ContentPage实例控件的基类

新建ContentPageBase.cs文件,创建类ContentPageBase继承于ContentPage

    public class ContentPageBase : ContentPage
{
public IObjectMapper ObjectMapper { get; set; } /// <summary>
/// Reference to the setting manager.
/// </summary>
public ISettingManager SettingManager { get; set; } /// <summary>
/// Reference to the localization manager.
/// </summary>
public ILocalizationManager LocalizationManager { get; set; } /// <summary>
/// Gets/sets name of the localization source that is used in this application service.
/// It must be set in order to use <see cref="L(string)"/> and <see cref="L(string,CultureInfo)"/> methods.
/// </summary>
protected string LocalizationSourceName { get; set; } /// <summary>
/// Gets localization source.
/// It's valid if <see cref="LocalizationSourceName"/> is set.
/// </summary>
protected ILocalizationSource LocalizationSource
{
get
{
if (LocalizationSourceName == null)
{
throw new AbpException("Must set LocalizationSourceName before, in order to get LocalizationSource");
} if (_localizationSource == null || _localizationSource.Name != LocalizationSourceName)
{
_localizationSource = LocalizationManager.GetSource(LocalizationSourceName);
} return _localizationSource;
}
}
private ILocalizationSource _localizationSource; /// <summary>
/// Constructor.
/// </summary>
protected ContentPageBase()
{
LocalizationSourceName = MauiBoilerplateConsts.LocalizationSourceName;
ObjectMapper = NullObjectMapper.Instance;
LocalizationManager = NullLocalizationManager.Instance;
} /// <summary>
/// Gets localized string for given key name and current language.
/// </summary>
/// <param name="name">Key name</param>
/// <returns>Localized string</returns>
protected virtual string L(string name)
{
return LocalizationSource.GetString(name);
} /// <summary>
/// Gets localized string for given key name and current language with formatting strings.
/// </summary>
/// <param name="name">Key name</param>
/// <param name="args">Format arguments</param>
/// <returns>Localized string</returns>
protected virtual string L(string name, params object[] args)
{
return LocalizationSource.GetString(name, args);
} /// <summary>
/// Gets localized string for given key name and specified culture information.
/// </summary>
/// <param name="name">Key name</param>
/// <param name="culture">culture information</param>
/// <returns>Localized string</returns>
protected virtual string L(string name, CultureInfo culture)
{
return LocalizationSource.GetString(name, culture);
} /// <summary>
/// Gets localized string for given key name and current language with formatting strings.
/// </summary>
/// <param name="name">Key name</param>
/// <param name="culture">culture information</param>
/// <param name="args">Format arguments</param>
/// <returns>Localized string</returns>
protected virtual string L(string name, CultureInfo culture, params object[] args)
{
return LocalizationSource.GetString(name, culture, args);
}
}

同理,若我们使用了其他控件类时,可以增加一个Base类作为实例控件的基类的

比如Popup控件,就编写一个PopupBase基类。

在这里我们编写了两个基类

​编辑

本地化配置

新建一个TranslateExtension.cs作为Xaml标签的本地化处理类

    [ContentProperty("Text")]
public class TranslateExtension : DomainService, IMarkupExtension
{
public TranslateExtension()
{
LocalizationSourceName = MauiBoilerplateConsts.LocalizationSourceName; }
public string Text { get; set; } public object ProvideValue(IServiceProvider serviceProvider)
{
if (Text == null)
return "";
var translation = L(Text);
return translation;
} }

在MauiBoilerplateLocalization.cs配置好SourceFiles

    public static void Configure(ILocalizationConfiguration localizationConfiguration)
{
localizationConfiguration.Sources.Add(
new DictionaryBasedLocalizationSource(MauiBoilerplateConsts.LocalizationSourceName,
new XmlEmbeddedFileLocalizationDictionaryProvider(
typeof(LocalizationConfigurer).GetAssembly(),
"MauiBoilerplate.Core.Localization.SourceFiles"
)
)
);
}

编写ViewModelBase

为实现Mvvm设计模式,页面需要绑定一个继承于ViewModelBase的类型

在ViewModelBase中,需要实现INotifyPropertyChanged以处理绑定成员变化时候的通知消息;

ViewModelBase集成于AbpServiceBase以方便ViewModel代码编写者使用常用的功能,比如字符串的本地化,配置,AutoMapper对象等。

    public abstract class ViewModelBase : AbpServiceBase, ISingletonDependency, INotifyPropertyChanged
{
public ViewModelBase()
{
LocalizationSourceName = MauiBoilerplateConsts.LocalizationSourceName;
} public event PropertyChangedEventHandler PropertyChanged; protected PropertyChangedEventHandler PropertyChangedHandler { get; } public void VerifyPropertyName(string propertyName)
{
Type type = GetType();
if (!string.IsNullOrEmpty(propertyName) && type.GetTypeInfo().GetDeclaredProperty(propertyName) == null)
throw new ArgumentException("找不到属性", propertyName);
} public virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler propertyChanged = PropertyChanged;
if (propertyChanged == null)
return;
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
} public virtual void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
if (PropertyChanged == null)
return;
string propertyName = GetPropertyName(propertyExpression);
if (string.IsNullOrEmpty(propertyName))
return;
RaisePropertyChanged(propertyName);
} protected static string GetPropertyName<T>(Expression<Func<T>> propertyExpression)
{
if (propertyExpression == null)
throw new ArgumentNullException(nameof(propertyExpression));
MemberExpression body = propertyExpression.Body as MemberExpression;
if (body == null)
throw new ArgumentException("参数不合法", nameof(propertyExpression));
PropertyInfo member = body.Member as PropertyInfo;
if (member == null)
throw new ArgumentException("找不到属性", nameof(propertyExpression));
return member.Name;
} }

至此,我们完成了数据库的配置,内容页基类与 ViewModel基类的编写,接下来可以制作我们的页面了。请看下一章将Abp移植进.NET MAUI项目(三):构建UI层 - 林晓lx - 博客园 (cnblogs.com)

项目地址

jevonsflash/maui-abp-sample (github.com)

将Abp移植进.NET MAUI项目(二):配置与基类编写的更多相关文章

  1. 将Abp移植进.NET MAUI项目(一):搭建项目

    ​ 前言 去年12月份做了MAUI混合开发框架的调研,想起来文章里给自己挖了个坑,要教大家如何把Abp移植进Maui项目,由于篇幅限制,将分为三个章节. 将Abp移植进.NET MAUI项目(一):搭 ...

  2. 四、spring集成ibatis进行项目中dao层基类封装

    Apache iBatis(现已迁至Google Code下发展,更名为MyBatis)是当前IT项目中使用很广泛的一个半自动ORM框架,区别于Hibernate之类的全自动框架,iBatis对数据库 ...

  3. ABP 集成 nswag 到 VUE 项目, 自动生成操作类代码

    记录日期: 2019-9-22 23:12:39 原文链接:https://www.cnblogs.com/Qbit/p/11569906.html 集成记录: npm install nswag - ...

  4. WPF开发时光之痕日记本(二)—— MVVM基类

    当我们用MVVM的时候要实现INotifyPropertyChanged,每次都要实现这个接口比较麻烦,所以基类的作用就体现出来了.代码如下: public class ViewModelBase : ...

  5. MVC+LINQToSQL的Repository模式之(二)数据基类

    namespace Data.TEST{    /// <summary>    /// 数据操作基类    /// </summary>    public abstract ...

  6. [MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构

    这是一篇系列博文.请关注我,学习更多.NET MAUI开发知识! [MAUI 项目实战] 手势控制音乐播放器(一): 概述与架构 [MAUI 项目实战] 手势控制音乐播放器(二): 手势交互 [MAU ...

  7. 使用ABP SignalR重构消息服务(二)

    使用ABP SignalR重构消息服务(二) 上篇使用ABP SignalR重构消息服务(一)主要讲的是SignalR的基础知识和前端如何使用SignalR,这段时间也是落实方案设计.这篇我主要讲解S ...

  8. Eclipse+Maven创建webapp项目<二> (转)

    Eclipse+Maven创建webapp项目<二> 1.开启eclipse,右键new——>other,如下图找到maven project 2.选择maven project,显 ...

  9. Python CRM项目二

    一.准备工作 如果没有配置基本的项目,请参考 http://www.cnblogs.com/luhuajun/p/7771196.html 当我们配置完成后首先准备我们的app 创建2个app分别对应 ...

  10. Vue小项目二手书商城:(四)详情页和购物车(emit、prop、computed)

    实现效果: 点击对应商品,对应的商品详情页出现,详情页里面还有“Add to cart”按钮和“×”退出按钮. 点击“Add to cart”可以将商品加入购物车,每件商品只能添加一次,如果把购物车的 ...

随机推荐

  1. 1.基于Label studio的训练数据标注指南:信息抽取(实体关系抽取)、文本分类等

    文本抽取任务Label Studio使用指南 1.基于Label studio的训练数据标注指南:信息抽取(实体关系抽取).文本分类等 2.基于Label studio的训练数据标注指南:(智能文档) ...

  2. 热门数据集提供【MNIST、鸢尾花、猫狗、CIFAR10、vegetables、Ox-Flowers17、pascalvoc】

    热门数据集提供[MNIST.鸢尾花.猫狗.CIFAR10.vegetables.Ox-Flowers17.pascalvoc] 简介: 鸢尾花数据集: 约150条数据,每条样本4个属性,共3个类别 M ...

  3. 【8】同步vscode配置和插件【导入导出】、再也不用担心换电脑重新安装插件了

    相关文章: [1]VScode中文界面方法-------超简单教程 [2]VScode搭建python和tensorflow环境 [3]VSCode 主题设置推荐,自定义配色方案,修改注释高亮颜色 [ ...

  4. 3.1 Windows驱动开发:内核远程堆分配与销毁

    在开始学习内核内存读写篇之前,我们先来实现一个简单的内存分配销毁堆的功能,在内核空间内用户依然可以动态的申请与销毁一段可控的堆空间,一般而言内核中提供了ZwAllocateVirtualMemory这 ...

  5. C/C++ BeaEngine 反汇编引擎

    反汇编引擎有很多,这个引擎没有Dll,是纯静态链接库,适合r3-r0环境,你可以将其编译为DLL文件,驱动强制注入到游戏进程中,让其快速反汇编,读取出反汇编代码并保存为txt文本,本地分析. 地址:h ...

  6. vue-cli3创建多页面应用

    首先用vue-cli3创建工程,我的全局安装了vue-cli2,又不想卸载掉:所以新建了一个文件夹安装vue-cli3:然后在该文件夹下创建工程: 同时安装vue-cli2和vue-cli3参考:ht ...

  7. Linux--如何查看磁盘的IO(top、iostat)

    问题背景: 在性能测试时,虽然测试出了结果,但是我们并不知道瓶颈是源端,还是目标端.例如我做上传和下载性能验证,从Linux服务器上向OSS集群上传和下载文件,虽然测试出了速率,但是并不知道上传是否存 ...

  8. LLM研究之-NVIDIA的CUDA

    一.什么是NVIDIA的CUDA CUDA(Compute Unified Device Architecture)是由NVIDIA公司开发的一个并行计算平台和应用程序编程接口(API),它允许软件开 ...

  9. HASHTEAM香山杯2023WP

    目录 前言 misc 签到题 web PHP_unserialize_pro Re URL从哪儿来 hello python pwn Move pwthon 附上c-python调试方法 crypto ...

  10. SavedStateHandle的介绍----ViewModel不具备保存状态数据的功能

    LiveData本身不能在进程销毁中存活,当内存不足时,Activity被系统杀死,ViewModel本身也会被销毁. 为了保存LiveData的数据,使用SavedStateHandle. 事故场景 ...