در قسمت قبل به معرفی postgresql پرداختیم; در این قسمت قصد ایجاد و راه اندازی یک api با استفاده از دیتابیس postgresql و استفاده از تکنولوژیهای آن را با استفاده از docker داریم.
ابتدا
با استفاده از دستور زیر یک پروژهی جدید asp.net core را ایجاد کنید:
dotnet new webapi --minimal -o YourDirectoryPath:\YourFolderName
سپس
فایل docker-compose.yaml را به روت پروژه اضافه کنید که شامل کانفیگهای زیر میباشد:
version: '3.1'
services:
db:
image: postgres
container_name: db
restart: always
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USERNAME: postgres
POSTGRES_DB: BloggingDb
ports:
- "5432:5432"
volumes:
- postgres_data:/data/db
adminer:
image: adminer
restart: always
ports:
- 8080:8080
pgadmin4:
image: dpage/pgadmin4
restart: always
environment:
PGADMIN_DEFAULT_EMAIL: pgadmin4@pgadmin.org
PGADMIN_DEFAULT_PASSWORD: admin
PGADMIN_CONFIG_SERVER_MODE: 'False'
ports:
- 5050:80
volumes:
- pgadmin:/var/lib/pgadmin
depends_on:
- db
volumes:
postgres_data:
pgadmin:
سپس با
اجرای دستور زیر در روت پروژه، سرویسها را راه اندازی کنید:
معرفی
سرویسهای استفاده شده در تنظیمات فایل بالا:
سرویس db :
نمونه ایمیج اصلی، volume، تنظیمات connection string در آن استفاده شده است.
سرویس adminer :
https://hub.docker.com/_/adminer /
Adminer - Database
management in a single PHP file
یک
برنامه تحت وب مدیریت پایگاه داده ساده میباشد که ویژگیها MySql را در کنار سرعت و
امنیت ارائه میدهد و در آدرس http://localhost:8080 / اجرا خواهد شد.
سرویس pgadmin4 :
pgAdmin - PostgreSQL
Tools
dpage/pgadmin4
- Docker Image | Docker Hub
در حال
حاضر این برنامه محبوبترین برنامه مدیریت پایگاه داده میباشد که ویژگیهای پیشرفتهای را نیز پوشش میدهد و در آدرس http://localhost:5050 / اجرا خواهد شد.
اکنون نوبت نوشتن کدها میباشد.
- تنظیم connection string در فایل appsettings.json:
"ConnectionStrings": {
"BloggingContext": "Username=postgres;Password=postgres;Server=localhost;Database=BloggingDb”
}
- و
همینطور پکیجهای زیر را به برنامه خود رفرنس دهید:
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Design
- مدلهای برنامه را در مسیر /Models ایجاد کنید:
namespace NpgsqlAPI.Models;
public class Post
{
public int PostId { get; set; }
public string Title { get; set; } = null!;
public string Content { get; set; } = null!;
public int BlogId { get; set; }
public Blog Blog { get; set; } = null!;
}
namespace NpgsqlAPI.Models;
public class Blog
{
public int BlogId { get; set; }
public string? Url { get; set; }
public List<Post>? Posts { get; set; }
}
- سپس BloggingContext را در مسیر /Data ایجاد کنید:
using Microsoft.EntityFrameworkCore;
using NpgsqlAPI.Models;
namespace NpgsqlAPI.Data;
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{
}
public DbSet<Blog> Blogs => Set<Blog>();
public DbSet<Post
- سپس
اینترفیس IBlogServices را در مسیر /Servicec/Blogs ایجاد کنید:
using NpgsqlAPI.Models;
namespace NpgsqlAPI.Services.Blogs;
public interface IBlogServices
{
Task<IEnumerable<Blog>> GetList();
Task<Blog?> Get(uint id);
Task<uint> Add(Blog obj);
Task AddRange(Blog[] obj);
Task Update(Blog obj);
Task UpdateRange(Blog[] obj);
Task Remove(uint id);
}
- و سپس
پیاده سازی آن را در فایل BlogEFServices و در کنار اینترفیس آن قرار دهید:
using Microsoft.EntityFrameworkCore;
using NpgsqlAPI.Data;
using NpgsqlAPI.Models;
namespace NpgsqlAPI.Services.Blogs;
public sealed class BlogEFServices : IBlogServices
{
private readonly BloggingContext _context;
public BlogEFServices(BloggingContext context)
{
_context = context;
}
public async Task<uint> Add(Blog obj)
{
await _context.Blogs.AddAsync(obj);
return (uint)await SaveChangesAsync();
}
public async Task AddRange(Blog[] obj)
{
await _context.Blogs.AddRangeAsync(obj);
await SaveChangesAsync();
}
public async Task<Blog?> Get(uint id)
{
return await _context.Blogs.FirstOrDefaultAsync(x=>x.BlogId == id);
}
public async Task<IEnumerable<Blog>> GetList()
{
return await _context.Blogs.ToListAsync();
}
public async Task Remove(uint id)
{
var entity = await Get(id);
_context.Blogs.Remove(entity!);
await SaveChangesAsync();
}
public async Task Update(Blog obj)
{
_context.Blogs.Update(obj);
await SaveChangesAsync();
}
public async Task UpdateRange(Blog[] obj)
{
_context.Blogs.UpdateRange(obj);
await SaveChangesAsync();
}
private async Task<int> SaveChangesAsync()
{
return await _context.SaveChangesAsync();
}
}
- اکنون endpointهای api را در فایل program.cs ایجاد کنید:
using System.Data;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using NpgsqlAPI.Services.Blogs;
using NpgsqlAPI.Data;
using NpgsqlAPI.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
string connectionString = builder.Configuration.GetConnectionString("BloggingContext")!;
builder.Services.AddDbContext<BloggingContext>(options =>
options.UseNpgsql(connectionString));
builder.Services.AddTransient<IDbConnection>(_ => new NpgsqlConnection(connectionString));
// builder.Services.AddScoped<IBlogServices, BlogDapperServices>();
// builder.Services.AddScoped<IBlogServices, BlogEFRawQueryServices>();
builder.Services.AddScoped<IBlogServices, BlogEFServices>();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.MapGet("/blogs", async (IBlogServices service) => await service.GetList())
.WithName("GetBlogs")
.WithOpenApi();
app.MapGet("/blogs/{id}", async (IBlogServices service, uint id) => await service.Get(id))
.WithName("GetBlog")
.WithOpenApi();
app.MapPost("/blogs", async (IBlogServices service, Blog blog) => await service.Add(blog))
.WithName("AddBlog")
.WithOpenApi();
app.MapDelete("/blogs/{id}", async (IBlogServices service, uint id) => await service.Remove(id))
.WithName("RemoveBlog")
.WithOpenApi();
app.MapPut("/blogs", async (IBlogServices service, Blog blog) => await service.Update(blog))
.WithName("UpdateBlog")
.WithOpenApi();
app.MapPut("/blogs/Bulk", async (IBlogServices service, Blog[] blogs) =>
await service.UpdateRange(blogs))
.WithName("UpdateBulkBlog")
.WithOpenApi();
app.MapPost("/blogs/Bulk", async (IBlogServices service, Blog[] blogs) =>
await service.AddRange(blogs))
.WithName("AddBulkBlog")
.WithOpenApi();
app.Run();
تمامی کدهای برنامه تا به اینجا نوشته شدهاند. اکنون migration را پس از اطمینان از اجرا بودن داکر اجرا
کنید
dotnet ef migrations add Init
dotnet ef database update
و برنامه را
اجرا و تست کنید.
کدهای کامل این مطلب