1. 描述
开发环境
- dotnet core 3.1.102
- SQL 2017
- vs code
- volo.abp 2.3.0
2. 下载模板项目
在abp.io或abp cli官网下载模板项目
3. 领域层开发
using System;
using System.Collections.Generic;
using Volo.Abp.Domain.Entities.Auditing;
namespace MyAbp.Domain.News
{
//1、新闻聚合
public class NewsItem:CreationAuditedAggregateRoot<Guid>
{
public virtual string Title { get; protected set; }
public virtual string Short { get; protected set; }
public virtual string Full { get; protected set; }
public virtual bool Published { get; protected set; }
public virtual DateTime? StartDateUtc { get; protected set; }
public virtual DateTime? EndDateUtc { get; protected set; }
public virtual bool AllowComments { get; protected set; }
public virtual int OrderBy{get;protected set;}
public virtual ICollection<NewsCategoryLine> Categorys { get; protected set; }
protected NewsItem() { }
}
}
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace MyAbp.Domain.News
{
//1、评论聚合
public class NewsComment:CreationAuditedAggregateRoot<Guid>
{
public virtual string CommentTitle { get; protected set; }
public virtual string CommentText { get; protected set; }
public virtual Guid NewsItemId { get; protected set; }
protected NewsComment(){}
}
}
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace MyAbp.Domain.News
{
//1、分类聚合
public class NewsCategory:CreationAuditedAggregateRoot<Guid>
{
public virtual string Name{get; protected set;}
protected NewsCategory(){}
}
}
using System;
using Volo.Abp.Domain.Entities;
namespace MyAbp.Domain.News
{
public class NewsCategoryLine:Entity
{
//1、分类映射聚合
public virtual Guid NewsItemId { get; protected set; }
public virtual Guid NewsCategoryId { get; protected set; }
protected NewsCategoryLine()
{
}
protected internal NewsCategoryLine(Guid newsItemId, Guid newsCategoryId)
{
NewsItemId = newsItemId;
NewsCategoryId = newsCategoryId;
}
public override object[] GetKeys()
{
return new object[] { NewsItemId, NewsCategoryId };
}
}
}
4. 基础设施层开发
- 添加实体:MyAbpDbContext.cs代码
using Microsoft.EntityFrameworkCore;
using MyAbp.Users;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Volo.Abp.Users.EntityFrameworkCore;
using MyAbp.Domain.News;
namespace MyAbp.EntityFrameworkCore
{
/* This is your actual DbContext used on runtime.
* It includes only your entities.
* It does not include entities of the used modules, because each module has already
* its own DbContext class. If you want to share some database tables with the used modules,
* just create a structure like done for AppUser.
*
* Don't use this DbContext for database migrations since it does not contain tables of the
* used modules (as explained above). See MyAbpMigrationsDbContext for migrations.
*/
[ConnectionStringName("Default")]
public class MyAbpDbContext : AbpDbContext<MyAbpDbContext>
{
public DbSet<AppUser> Users { get; set; }
/* Add DbSet properties for your Aggregate Roots / Entities here.
* Also map them inside MyAbpDbContextModelCreatingExtensions.ConfigureMyAbp
*/
//2、添加实体
public DbSet<NewsItem> NewsItems { get; set; }
public DbSet<NewsComment> NewsComments { get; set; }
public DbSet<NewsCategory> NewsCategorys { get; set; }
public DbSet<NewsCategoryLine> NewsCategoryLines { get; set; }
public MyAbpDbContext(DbContextOptions<MyAbpDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/* Configure the shared tables (with included modules) here */
builder.Entity<AppUser>(b =>
{
b.ToTable("AbpUsers"); //Sharing the same table "AbpUsers" with the IdentityUser
b.ConfigureByConvention();
b.ConfigureAbpUser();
//Moved customization to a method so we can share it with the MyAbpMigrationsDbContext class
b.ConfigureCustomUserProperties();
});
/* Configure your own tables/entities inside the ConfigureMyAbp method */
builder.ConfigureMyAbp();
}
}
}
- 配置实体:MyAbpDbContextModelCreatingExtensions.cs代码
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Volo.Abp;
using Volo.Abp.Users;
using Volo.Abp.EntityFrameworkCore.Modeling;
using MyAbp.Domain.News;
namespace MyAbp.EntityFrameworkCore
{
public static class MyAbpDbContextModelCreatingExtensions
{
public static void ConfigureMyAbp(this ModelBuilder builder)
{
Check.NotNull(builder, nameof(builder));
/* Configure your own tables/entities inside here */
//builder.Entity<YourEntity>(b =>
//{
// b.ToTable(MyAbpConsts.DbTablePrefix + "YourEntities", MyAbpConsts.DbSchema);
// //...
//});
// 3、配置实体
builder.Entity<NewsItem>(b =>
{
b.ToTable(MyAbpConsts.DbTablePrefix + "NewsItems", MyAbpConsts.DbSchema);
b.Property(x => x.Title).IsRequired().HasMaxLength(128);
b.ConfigureByConvention();
});
builder.Entity<NewsComment>(b =>
{
b.ToTable(MyAbpConsts.DbTablePrefix + "NewsComments", MyAbpConsts.DbSchema);
b.Property(x => x.CommentTitle).IsRequired().HasMaxLength(128);
b.ConfigureByConvention();
});
builder.Entity<NewsCategory>(b =>
{
b.ToTable(MyAbpConsts.DbTablePrefix + "NewsCategorys", MyAbpConsts.DbSchema);
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
b.ConfigureByConvention();
});
builder.Entity<NewsCategoryLine>(b =>
{
b.ToTable(MyAbpConsts.DbTablePrefix + "NewsCategoryLines", MyAbpConsts.DbSchema);
b.HasKey(nc => new { nc.NewsItemId, nc.NewsCategoryId });
b.HasOne<NewsCategory>().WithMany().HasForeignKey(pd => pd.NewsCategoryId).IsRequired();
b.HasOne<NewsItem>().WithMany(ni=> ni.Categorys).HasForeignKey(ni => ni.NewsItemId).IsRequired();
b.HasIndex(nc => new { nc.NewsItemId, nc.NewsCategoryId });
b.ConfigureByConvention();
});
}
public static void ConfigureCustomUserProperties<TUser>(this EntityTypeBuilder<TUser> b)
where TUser: class, IUser
{
//b.Property<string>(nameof(AppUser.MyProperty))...
}
}
}
5. 数据迁移
添加
dotnet ef migrations add newsitem --startup-project .\src\MyAbp.HttpApi.Host\ -p .\src\MyAbp.EntityFrameworkCore.DbMigrations\
迁移
dotnet ef database update --startup-project .\src\MyAbp.HttpApi.Host\ -p .\src\MyAbp.EntityFrameworkCore.DbMigrations\