建立和注册Context
- 安装包 >>> Infrastructure项目
- Microsoft.EntityFrameworkCore.Design
- Microsoft.EntityFrameworkCore.[Sqlite][SqlServer][MySql]
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
Install-Package Microsoft.EntityFrameworkCore.SqlServer
- 建立Context
- Entities >>> Core项目
public class Post : Entity
{
// public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public string Author { get; set; }
public DateTime LastModified { get; set; }
}
- Context:DbContext >>>Infrastructure项目
public class ApplicationContext:DbContext
{
public ApplicationContext(DbContextOptions<ApplicationContext> options):base(options)
{
}
public DbSet<Post> Posts { get; set; }
}
- Startup里注册Context
//注册Dbcontxt
services.AddDbContext<ApplicationContext>(options =>
{
//var contectionString = "Data Source = localhost; Database = Blog.db; User = sa; Password = password";
var contectionString = "Data Source = .;Database = Blog.db;Integrated Security=True";
options.UseSqlServer(contectionString);
});
- 数据库迁移
- 快速调出package manager console
Alt + T
N
O
- add-migration [Name]
-
update-database
Migrations
- 添加种子数据
- Seed.cs
public class Seed
{
public static async Task SeedAsync(ApplicationContext applicationContext,
ILoggerFactory loggerFactory, int retry = 0)
{
int retryForAvailability = retry;
try
{
// TODO: Only run this if using a real database
// myContext.Database.Migrate();
if (!applicationContext.Posts.Any())
{
applicationContext.Posts.AddRange(
new List<Post>{
new Post{
Title = "Post Title 1",
Body = "Post Body 1",
Author = "Dave",
LastModified = DateTime.Now
},
new Post{
Title = "Post Title 2",
Body = "Post Body 2",
Author = "Dave",
LastModified = DateTime.Now
},
new Post{
Title = "Post Title 3",
Body = "Post Body 3",
Author = "Dave",
LastModified = DateTime.Now
},
new Post{
Title = "Post Title 4",
Body = "Post Body 4",
Author = "Dave",
LastModified = DateTime.Now
},
new Post{
Title = "Post Title 5",
Body = "Post Body 5",
Author = "Dave",
LastModified = DateTime.Now
},
new Post{
Title = "Post Title 6",
Body = "Post Body 6",
Author = "Dave",
LastModified = DateTime.Now
},
new Post{
Title = "Post Title 7",
Body = "Post Body 7",
Author = "Dave",
LastModified = DateTime.Now
},
new Post{
Title = "Post Title 8",
Body = "Post Body 8",
Author = "Dave",
LastModified = DateTime.Now
}
}
);
await applicationContext.SaveChangesAsync();
}
}
catch (Exception ex)
{
if (retryForAvailability < 10)
{
retryForAvailability++;
var logger = loggerFactory.CreateLogger<Seed>();
logger.LogError(ex.Message);
await SeedAsync(applicationContext, loggerFactory, retryForAvailability);
}
}
}
}
- Program中调用
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
try
{
var applicationContext = services.GetRequiredService<ApplicationContext>();
//调用方法创建种子数据
Seed.SeedAsync(applicationContext, loggerFactory).Wait();
}
catch (Exception e)
{
var logger = loggerFactory.CreateLogger<Program>();
logger.LogError(e, "Error occured seeding the Database.");
}
}
host.Run();
}
- 添加PostController
[Route("api/posts")]
public class PostController : Controller
{
private readonly ApplicationContext _applicationContext;
public PostController(ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
}
[HttpGet]
public async Task<IActionResult> Get()
{
var posts = await _applicationContext.Posts.ToListAsync();
return Ok(posts);
}
}
-
成功
种子文件成功
Repository 仓储服务
与持久化技术无关(使用其他Drapper等替代EF Core)、易于测试、代码重用
IRepository接口:依赖注入、松耦合、DIP原则、易于测试
- 注入的是接口,而不是具体的类。如果注入Repository这个类,Controller就依赖了Repository,这样就是高级别模块依赖了低级别模块,违反了DIP原则! 应该都依赖于抽象IRepository接口。
- IRepository >>> Core.Interface
public interface IPostRepository
{
Task<IEnumerable<Post>> GetAllPostsAsync();
}
- Repository >>> Infrastructure.Repositories
public class PostRepository : IPostRepository
{
//注入DbContext
private readonly ApplicationContext _applicationContext;
public PostRepository(ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
}
public async Task<IEnumerable<Post>> GetAllPostsAsync()
{
return await _applicationContext.Posts.ToListAsync();
}
}
- Startup中注册服务
//注册仓储服务
services.AddScoped<IPostRepository, PostRepository>();
- 服务注册生命周期
-
Transient
: 每次其它的类请求(不是指HTTP Request)都会创建一个新的实例,它比较适合轻量级的无状态的(Stateless)的service. -
Scope
: 每次HTTP请求会创建一个实例。 -
Singleton
: 在第一次请求的时候就会创建一个实例,以后也只有这一个实例; 或者在ConfigureServices这段代码运行的时候创建唯一一个实例。
-
- 修改Controller,注入Repository
[Route("api/posts")]
public class PostController : Controller
{
private readonly IPostRepository _postRepository;
public PostController(IPostRepository postRepository)
{
_postRepository = postRepository;
}
[HttpGet]
public async Task<IActionResult> Get()
{
var posts = await _postRepository.GetAllPostsAsync();
return Ok(posts);
}
}
Unit of Work 仓储服务
- IUntiOfWork >>> Core.Interface
public interface IUnitOfWork
{
Task<bool> SaveAsync();
}
- UnitOfWork >>> Infrastructure.Database
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationContext _applicationContext;
public UnitOfWork(ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
}
public async Task<bool> SaveAsync()
{
return await _applicationContext.SaveChangesAsync() > 0;
}
}
- Startup中注册服务
//注册仓储服务
services.AddScoped<IUnitOfWork , UnitOfWork >();
- Repository添加AddPost方法
public void AddPost(Post post)
{
_applicationContext.Posts.Add(post);
}
- 修改controller, 注入IUnitOfWork, Post()方法中调用
[Route("api/posts")]
public class PostController : Controller
{
private readonly IPostRepository _postRepository;
private readonly IUnitOfWork _unitOfWork;
public PostController(
IPostRepository postRepository,
IUnitOfWork unitOfWork)
{
_postRepository = postRepository;
_unitOfWork = unitOfWork;
}
[HttpGet]
public async Task<IActionResult> Get()
{
var posts = await _postRepository.GetAllPostsAsync();
return Ok(posts);
}
[HttpPost]
public async Task<IActionResult> Post()
{
var newPost = new Post
{
Title = "ENFI",
Author = "ZGX",
Body = "adskfasdjfladsjfa;ldsfads",
LastModified = DateTime.Now
};
_postRepository.AddPost(newPost);
await _unitOfWork.SaveAsync();
return Ok();
}
}
Entity约束
- PostConfiguration.cs >>> Infrastructure.EntityConfiguration
public class PostConfiguration : IEntityTypeConfiguration<Post>
{
public void Configure(EntityTypeBuilder<Post> builder)
{
builder.Property(x => x.Author).IsRequired().HasMaxLength(50);
builder.Property(x => x.Title).IsRequired().HasMaxLength(100);
builder.Property(x => x.Body).IsRequired().HasColumnType("nvarchar(max)");
}
}
- DbContext中重写OnModel
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new PostConfiguration());
}
网友评论