我們?nèi)匀皇褂谩稄牧汩_始進行ABP項目開發(fā)》系列中的項目需求。
Poem需求描述
我們使用一個簡單的項目來說明問題,這是一款針對全唐詩的小應(yīng)用,可以對唐詩和作者進行簡單的查詢,可以對唐詩進行自定義的分類,還有一些簡單的小游戲,比如可以將一句唐詩的順序打亂,用戶進行正確的排序等。數(shù)據(jù)庫已經(jīng)有了,在Sql Server中,將來可能需要支持Sqlite。數(shù)據(jù)模型如下:

相關(guān)的數(shù)據(jù)庫腳本發(fā)布在這里:Poem相關(guān)數(shù)據(jù)庫表的Sql語句
增加領(lǐng)域?qū)?/h2>
在解決方案中增加一個新的.Net Core類庫項目作為領(lǐng)域?qū)?,命名命名為ZL.AbpNext.Poem.Core:

按照[從零開始學習ABP vNext開發(fā) (一)——從控制臺項目入手]中“創(chuàng)建Abp模塊”的描述,創(chuàng)建新的模塊,名稱為PoemCoreModule:
using Volo.Abp.Modularity;
namespace ZL.AbpNext.Poem.Core
{
public class PoemCoreModule:AbpModule
{
}
}
然后創(chuàng)建一個子目錄,名稱為Poems,在這個目錄中創(chuàng)建第一個實體,名稱為Poet:
using Volo.Abp.Domain.Entities;
namespace ZL.AbpNext.Poem.Core.Poems
{
/// <summary>
/// 詩人,從ABP Entity派生
/// </summary>
public class Poet : Entity<int>
{
/// <summary>
/// 姓名
/// </summary>
public virtual string Name { get; set; }
/// <summary>
/// 介紹
/// </summary>
public virtual string Description { get; set; }
}
}
使用EF連接數(shù)據(jù)庫
下面,創(chuàng)建數(shù)據(jù)訪問層,使用EF從數(shù)據(jù)庫中獲取數(shù)據(jù)。在解決方案中增加另一個類庫項目,命名為ZL.AbpNext.Poem.EF,使用Nuget程序包管理器,安裝如下程序包:
- Microsoft.EntityFrameworkCore.SqlServer
- Volo.Abp.EntityFrameworkCore
- Volo.Abp.EntityFrameworkCore.SqlServer
然后,可以創(chuàng)建需要的DbContext,這里,Abp vNext與前一代Abp有很大的區(qū)別。
首先,需要為DbContext創(chuàng)建一個接口:
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using ZL.AbpNext.Poem.Core.Poems;
namespace ZL.AbpNext.Poem.EF.EntityFramework
{
[ConnectionStringName("Poem")]
public interface IPoemDbContext : IEfCoreDbContext
{
DbSet<Poet> Poets { get; set; }
}
}
接下來創(chuàng)建DbContext類:
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
using ZL.AbpNext.Poem.Core.Poems;
namespace ZL.AbpNext.Poem.EF.EntityFramework
{
[ConnectionStringName("Poem")]
public class PoemDbContext : AbpDbContext<PoemDbContext>,IPoemDbContext
{
public virtual DbSet<Poet> Poets { get; set; }
public PoemDbContext(DbContextOptions<PoemDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//映射Poet到數(shù)據(jù)庫表
modelBuilder.Entity<Poet>(b =>
{
b.ToTable("Poet");
//映射實體與數(shù)據(jù)庫中的字段,將Id映射到數(shù)據(jù)庫表的PoetID字段
b.Property(p => p.Id)
.HasColumnName("PoetID");
b.ConfigureByConvention();
});
}
}
}
我們已經(jīng)看到了Abp vNext在DbContext上進行的改進:1)增加了ConnectionStringName標記,可以自動從配置文件讀取連接字符串信息。2)增加了DbContext的接口。
這里需要注意的是:Abp的實體都是從Entity中繼承的,使用Id作為關(guān)鍵字標識,而我們已經(jīng)存在的數(shù)據(jù)庫表的關(guān)鍵字字段名是PoetID,這就需要在OnModelCreating中進行映射。
接下來我們創(chuàng)建數(shù)據(jù)模塊PoemDataModule:
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
using ZL.AbpNext.Poem.Core;
using ZL.AbpNext.Poem.EF.EntityFramework;
namespace ZL.AbpNext.Poem.EF
{
[DependsOn(
typeof(PoemCoreModule),
typeof(AbpEntityFrameworkCoreModule)
)]
public class PoemDataModule:AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAbpDbContext<PoemDbContext>(options =>
{
options.AddDefaultRepositories(includeAllEntities: true);
});
Configure<AbpDbContextOptions>(options =>
{
/* The main point to change your DBMS.
* See also BookStoreMigrationsDbContextFactory for EF Core tooling. */
options.UseSqlServer();
});
}
}
}
這里也有很大的改進,很多初始化的工作不需要在PreInitializes中進行處理,在ConfigureServices中,以更符合.Net Core的方式進行處理。這段代碼為所有實體生成缺省的Repository:
context.Services.AddAbpDbContext<PoemDbContext>(options =>
{
options.AddDefaultRepositories(includeAllEntities: true);
});
對于通用的增刪改等操作,不需要再編寫重復的代碼。
改造控制臺客戶端訪問數(shù)據(jù)庫
現(xiàn)在我們改造客戶端,使它可以調(diào)用我們新編寫的模塊,訪問數(shù)據(jù)庫中的詩人數(shù)據(jù)。
首先,增加項目依賴項,項目結(jié)構(gòu)如下:

還需要在項目中增加appsettings.json,在配置文件中設(shè)置數(shù)據(jù)庫鏈接字符串:
{
"ConnectionStrings": {
"Poem": "Server=localhost;Database=PoemNew;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"exclude": [
"**/bin",
"**/bower_components",
"**/jspm_packages",
"**/node_modules",
"**/obj",
"**/platforms"
]
}
注意:這個文件需要設(shè)置為“如果較新則復制”
圖片.png
然后,在PoemConsoleClientModel中增加對PoemCoreModule和PoemDataModule的依賴:
using Volo.Abp.Modularity;
using ZL.AbpNext.Poem.Core;
using ZL.AbpNext.Poem.EF;
namespace ZL.AbpNext.Poem.ConsoleClient
{
[DependsOn(
typeof(PoemCoreModule),
typeof(PoemDataModule))]
public class PoemConsoleClientModule:AbpModule
{
}
}
接下來,我們改造Service:
using System;
using System.Linq;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using ZL.AbpNext.Poem.Core.Poems;
namespace ZL.AbpNext.Poem.ConsoleClient
{
public class Service : ITransientDependency
{
IRepository<Poet> repository;
IUnitOfWorkManager uowManager;
public Service(IRepository<Poet> repository, IUnitOfWorkManager uowManager)
{
this.repository = repository;
this.uowManager = uowManager;
}
public void Run()
{
//Console.WriteLine("你好");
using (var uow = uowManager.Begin(new AbpUnitOfWorkOptions()))
{
//獲取第一個詩人
var poet = repository.FirstOrDefault();
Console.WriteLine(poet.Name);
}
}
}
}
由于框架支持依賴注入,所以,我們只需要在構(gòu)造函數(shù)中增加需要的服務(wù)就可以了,不需要關(guān)心如何獲取這些服務(wù)。這里我們需要Poet的repository,和執(zhí)行執(zhí)行工作單元的管理器,所以在構(gòu)造函數(shù)中增加這兩個參數(shù)。在執(zhí)行方法中,就可以使用repository獲取數(shù)據(jù)了。
到這里改造就完成了,主程序Program不需要修改。運行結(jié)果如下:

小結(jié)
- 解決方案中的每個項目都是一個ABP模塊,在模塊中定義模塊之間的依賴關(guān)系。
- 使用AbpApplicationFactory創(chuàng)建需要的模塊,并調(diào)用Initialize進行模塊初始化。
- 可以使用ServiceProvider.GetService獲取需要使用的對象。
- 在模塊的ConfigureServices方法中進行參數(shù)設(shè)置。
下一步工作
下一步,我們需要增加其它幾個實體到Poem.Core中,并增加應(yīng)用層(Application)。
