2024. 7. 5. 19:55ㆍDevelopment👩🏻🦳/C#


프로젝트 마지막 구현 사항이며 API 연동 및 데이터 베이스 연동은
com을 이용한 통신우회 방법을 쓰기 이전 버전에서 구현했습니다

1. 프로젝트 개요 및 초기 설정
안녕하세요! 오늘은 제가 최근 프로젝트를 진행하면서 겪었던 백엔드 관련 구현 사항과 에러 해결 과정을 공유하려고 합니다. 이번 포스팅은 시리즈 중 첫 번째로, 프로젝트 개요와 초기 설정에 대해 다룰 예정입니다. 이 과정에서 발생한 문제들과 그 해결 방법을 단계별로 설명하겠습니다.
프로젝트 개요: 이번 프로젝트는 작업 지시서 관리 시스템을 구축하는 것이 목표였습니다. 이 시스템은 다양한 작업 지시서를 생성, 조회, 수정, 삭제할 수 있는 기능을 제공합니다. 백엔드는 ASP.NET Core와 Entity Framework Core를 사용하여 데이터베이스와 상호 작용하도록 설계했습니다. 데이터베이스는 MySQL을 사용하였고, 주요 테이블은 **WorkInstruction**이라는 작업 지시서를 저장하는 테이블이었습니다.
초기 설정
1. 프로젝트 생성 및 기본 구조 설정: 첫 단계로, ASP.NET Core 프로젝트를 생성했습니다. 이 과정에서 기본적인 프로젝트 구조를 설정하고, 필요한 패키지를 설치했습니다.
bash코드 복사
dotnet new webapi -n WorkManagementSystem
cd WorkManagementSystem
dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Pomelo.EntityFrameworkCore.MySql
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package Microsoft.Extensions.Logging
이후, 데이터베이스와의 연결을 설정하기 위해 appsettings.json 파일에 MySQL 연결 문자열을 추가했습니다.
json코드 복사
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=plc_data_model1;User=root;Password=Alejd1785!;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
2. 데이터베이스 컨텍스트 설정: 다음으로, 데이터베이스 컨텍스트 클래스를 생성했습니다. AppDbContext 클래스는 Entity Framework Core에서 DbContext를 상속받아 데이터베이스와의 상호작용을 담당합니다.
csharp코드 복사
using Microsoft.EntityFrameworkCore;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
namespace WindowsFormsApp1Core.SQLModels
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<WorkInstruction> WorkInstructions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
string connectionString = "Server=localhost;Database=plc_data_model1;User=root;Password=Alejd1785!;";
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
}
}
}
}
3. WorkInstruction 모델 정의:WorkInstruction 모델은 작업 지시서의 구조를 정의합니다. 이 클래스는 작업 지시서의 다양한 속성을 포함하고 있습니다.
csharp코드 복사
using System;
using System.ComponentModel.DataAnnotations;
namespace WindowsFormsApp1Core.WorkManagementSystem.WMModels
{
public class WorkInstruction
{
[Key]
public string TaskName { get; set; }
public string Content { get; set; }
public DateTime Date { get; set; }
public string Writer { get; set; }
public string Priority { get; set; }
public bool IsCompleted { get; set; }
}
}
4. DI 설정 및 서비스 등록: 이제 Program.cs 파일에서 **AppDbContext**와 **WorkInstructionService**를 DI 컨테이너에 등록하여, 프로젝트 전체에서 사용할 수 있도록 설정합니다.
csharp코드 복사
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using WindowsFormsApp1Core.SQLModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMSrvs;
using Microsoft.Extensions.Logging;
public static class Program
{
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureServices((context, services) =>
{
services.AddDbContext<AppDbContext>(options =>
options.UseMySql(
context.Configuration.GetConnectionString("DefaultConnection"),
ServerVersion.AutoDetect(context.Configuration.GetConnectionString("DefaultConnection"))
));
services.AddScoped<WorkInstructionService>();
services.AddControllersWithViews();
});
webBuilder.Configure((context, app) =>
{
if (context.HostingEnvironment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
});
});
}
5. 서비스 클래스 구현:WorkInstructionService 클래스는 실제 비즈니스 로직을 구현합니다. 데이터베이스에서 작업 지시서를 생성, 조회, 수정, 삭제하는 메서드를 포함하고 있습니다.
csharp코드 복사
using System.Collections.Generic;
using System.Threading.Tasks;
using WindowsFormsApp1Core.SQLModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.WorkManagementSystem.WMSrvs
{
public class WorkInstructionService
{
private readonly AppDbContext _context;
private readonly ILogger<WorkInstructionService> _logger;
public WorkInstructionService(AppDbContext context, ILogger<WorkInstructionService> logger)
{
_context = context;
_logger = logger;
}
public async Task<IEnumerable<WorkInstruction>> GetWorkInstructionsAsync()
{
try
{
return await _context.WorkInstructions.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
throw;
}
}
public async Task AddWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
_context.WorkInstructions.Add(workInstruction);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
throw;
}
}
public async Task UpdateWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
var existing = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == workInstruction.TaskName);
if (existing != null)
{
existing.Content = workInstruction.Content;
existing.Date = workInstruction.Date;
existing.Writer = workInstruction.Writer;
existing.Priority = workInstruction.Priority;
existing.IsCompleted = workInstruction.IsCompleted;
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", workInstruction.TaskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
throw;
}
}
public async Task DeleteWorkInstructionAsync(string taskName)
{
try
{
var workInstruction = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
if (workInstruction != null)
{
_context.WorkInstructions.Remove(workInstruction);
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", taskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
throw;
}
}
public async Task<WorkInstruction> GetWorkInstructionByTaskNameAsync(string taskName)
{
try
{
return await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instruction by task name");
throw;
}
}
}
}
6. 컨트롤러 구현: 마지막으로, WorkInstructionController 클래스를 작성하여 클라이언트 요청을 처리합니다. 이 컨트롤러는 RESTful API를 제공하여 작업 지시서를 관리합니다.
csharp코드 복사
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMSrvs;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.Dashboard.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class WorkInstructionController : ControllerBase
{
private readonly WorkInstructionService _service;
private readonly ILogger<WorkInstructionController> _logger;
public WorkInstructionController(AppDbContext context, ILogger<WorkInstructionController> logger)
{
_service = new WorkInstructionService(context, logger);
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<WorkInstruction>>> Get()
{
try
{
var workInstructions = await _service.GetWorkInstructionsAsync();
return Ok(workInstructions);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
return StatusCode(500, "Internal server error");
}
}
[HttpPost]
public async Task<ActionResult<WorkInstruction>> Post(WorkInstruction workInstruction)
{
try
{
await _service.AddWorkInstructionAsync(workInstruction);
return CreatedAtAction(nameof(Get), new { id = workInstruction.TaskName }, workInstruction);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpPut("{taskName}")]
public async Task<IActionResult> Put(string taskName, WorkInstruction workInstruction)
{
try
{
var existingWorkInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (existingWorkInstruction == null)
{
return NotFound();
}
await _service.UpdateWorkInstructionAsync(workInstruction);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpDelete("{taskName}")]
public async Task<IActionResult> Delete(string taskName)
{
try
{
var workInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (workInstruction == null)
{
return NotFound();
}
await _service.DeleteWorkInstructionAsync(taskName);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
return StatusCode(500, "Internal server error");
}
}
}
}
결론:
이와 같이 프로젝트의 초기 설정을 완료했습니다. 다음 포스팅에서는 본격적으로 발생한 오류와 그 해결 방법을 다루겠습니다. 이 과정에서 Entity Framework Core와 관련된 다양한 문제와 이를 해결하는 과정을 통해 여러분도 비슷한 문제를 해결할 수 있도록 돕겠습니다.
2. 에러 분석 및 해결 (API)
프로젝트 진행 중에 마주한 API 관련 오류를 분석하고 해결하는 과정을 공유하겠습니다. 프로젝트 초기 설정 이후, 실제 기능을 구현하면서 다양한 에러가 발생했는데, 이 과정에서 배우고 해결한 내용을 단계별로 정리하였습니다.
에러 분석
1. CS1061 오류:
오류 메시지: 'WorkInstructionService' does not contain a definition for 'DeleteWorkInstruction' and no accessible extension method 'DeleteWorkInstruction' accepting a first argument of type 'WorkInstructionService' could be found.
원인 분석:
- WorkInstructionService 클래스에 DeleteWorkInstruction, GetWorkInstructions, AddWorkInstruction 등의 메서드 정의가 없다는 메시지입니다.
- AppDbContext 클래스에 WorkInstructions 속성이 없다는 것을 의미할 수 있습니다.
2. CS7036 오류:
오류 메시지: There is no argument given that corresponds to the required formal parameter 'context' of 'WorkInstructionService.WorkInstructionService(AppDbContext)'.
원인 분석:
- **WorkInstructionService**의 생성자가 **context**라는 AppDbContext 타입의 매개변수를 필요로 하지만, 이를 제공하지 않았습니다.
오류 해결 단계
단계 1: 클래스 정의 및 메서드 확인
- WorkInstructionService 클래스에 모든 필요한 메서드(DeleteWorkInstruction, GetWorkInstructions, AddWorkInstruction 등)가 정의되어 있는지 확인합니다.
- AppDbContext 클래스에 WorkInstructions DbSet이 정의되어 있는지 확인합니다.
단계 2: 생성자 매개변수 확인
- **WorkInstructionService**를 인스턴스화할 때 AppDbContext 인스턴스를 전달하는지 확인합니다.
단계 3: Using 문 및 참조 확인
- 파일 상단에 필요한 네임스페이스에 대한 using 문이 있는지 확인합니다.
파일 검토
1. WorkInstructionService.cs
우선 WorkInstructionService 클래스에 메서드들이 정의되어 있는지 확인하겠습니다.
csharp코드 복사
using System.Collections.Generic;
using System.Threading.Tasks;
using WindowsFormsApp1Core.SQLModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.WorkManagementSystem.WMSrvs
{
public class WorkInstructionService
{
private readonly AppDbContext _context;
private readonly ILogger<WorkInstructionService> _logger;
public WorkInstructionService(AppDbContext context, ILogger<WorkInstructionService> logger)
{
_context = context;
_logger = logger;
}
public async Task<IEnumerable<WorkInstruction>> GetWorkInstructionsAsync()
{
try
{
return await _context.WorkInstructions.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
throw;
}
}
public async Task AddWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
_context.WorkInstructions.Add(workInstruction);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
throw;
}
}
public async Task UpdateWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
var existing = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == workInstruction.TaskName);
if (existing != null)
{
existing.Content = workInstruction.Content;
existing.Date = workInstruction.Date;
existing.Writer = workInstruction.Writer;
existing.Priority = workInstruction.Priority;
existing.IsCompleted = workInstruction.IsCompleted;
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", workInstruction.TaskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
throw;
}
}
public async Task DeleteWorkInstructionAsync(string taskName)
{
try
{
var workInstruction = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
if (workInstruction != null)
{
_context.WorkInstructions.Remove(workInstruction);
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", taskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
throw;
}
}
public async Task<WorkInstruction> GetWorkInstructionByTaskNameAsync(string taskName)
{
try
{
return await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instruction by task name");
throw;
}
}
}
}
2. AppDbContext.cs
이제 AppDbContext 클래스에 WorkInstructions DbSet이 정의되어 있는지 확인합니다.
csharp코드 복사
using Microsoft.EntityFrameworkCore;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
namespace WindowsFormsApp1Core.SQLModels
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<WorkInstruction> WorkInstructions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
string connectionString = "Server=localhost;Database=plc_data_model1;User=root;Password=Alejd1785!;";
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
}
}
}
}
3. WorkInstructionServiceCtrl.cs
WorkInstructionService 인스턴스를 생성할 때 **AppDbContext**를 전달하는지 확인합니다.
csharp코드 복사
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMSrvs;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.Dashboard.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class WorkInstructionController : ControllerBase
{
private readonly WorkInstructionService _service;
private readonly ILogger<WorkInstructionController> _logger;
public WorkInstructionController(AppDbContext context, ILogger<WorkInstructionController> logger)
{
_service = new WorkInstructionService(context, logger);
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<WorkInstruction>>> Get()
{
try
{
var workInstructions = await _service.GetWorkInstructionsAsync();
return Ok(workInstructions);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
return StatusCode(500, "Internal server error");
}
}
[HttpPost]
public async Task<ActionResult<WorkInstruction>> Post(WorkInstruction workInstruction)
{
try
{
await _service.AddWorkInstructionAsync(workInstruction);
return CreatedAtAction(nameof(Get), new { id = workInstruction.TaskName }, workInstruction);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpPut("{taskName}")]
public async Task<IActionResult> Put(string taskName, WorkInstruction workInstruction)
{
try
{
var existingWorkInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (existingWorkInstruction == null)
{
return NotFound();
}
await _service.UpdateWorkInstructionAsync(workInstruction);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpDelete("{taskName}")]
public async Task<IActionResult> Delete(string taskName)
{
try
{
var workInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (workInstruction == null)
{
return NotFound();
}
await _service.DeleteWorkInstructionAsync(taskName);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
return StatusCode(500, "Internal server error");
}
}
}
}
500 내부 서버 오류 해결
문제: 500 내부 서버 오류는 주로 서버에서 발생하는 예외로 인해 응답이 실패하는 경우입니다. 이 문제를 해결하기 위해 몇 가지 점검 사항을 확인해 보았습니다.
확인할 항목들:
- 데이터베이스 연결 문자열:
- appsettings.json 또는 **AppDbContext**에서 사용한 연결 문자열이 올바른지 확인합니다.
- WorkInstructionService 클래스의 구현:
- 이 서비스 클래스의 메서드들이 올바르게 정의되어 있는지 확인합니다.
- 의존성 주입(DI) 설정:
- **Program.cs**에서 **AppDbContext**와 **WorkInstructionService**가 제대로 등록되었는지 확인합니다.
결론
이번 포스팅에서는 API 관련 오류를 분석하고 해결하는 과정을 살펴보았습니다. 에러 메시지를 기반으로 문제를 분석하고, 필요한 수정 사항을 적용하여 문제를 해결하는 방법을 배웠습니다. 다음 포스팅에서는 데이터베이스 마이그레이션 및 기타 발생한 문제를 해결하는 과정을 다루겠습니다.
4. 의존성 설치 및 설정
이 포스팅에서는 프로젝트에 필요한 의존성 설치 및 설정 방법을 다루겠습니다. 특히, NuGet 패키지를 설치하고, 프로젝트의 설정 파일들을 수정하는 과정을 설명합니다. 이러한 설정은 프로젝트가 정상적으로 빌드되고 실행되기 위해 필수적입니다.
NuGet 패키지 설치
프로젝트에서 사용할 NuGet 패키지를 설치합니다. 여기에서는 Pomelo.EntityFrameworkCore.MySql, Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Tools 패키지를 설치합니다.
1. 패키지 설치 명령
패키지 관리 콘솔에서 다음 명령을 실행하여 필요한 패키지를 설치합니다.
powershell코드 복사
Install-Package Pomelo.EntityFrameworkCore.MySql
Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.Tools
데이터베이스 연결 설정
1. appsettings.json 설정
데이터베이스 연결 문자열을 설정하여 프로젝트가 데이터베이스에 접근할 수 있도록 합니다.
json코드 복사
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=plc_data_model1;User=root;Password=Alejd1785!;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
AppDbContext 클래스 설정
1. AppDbContext.cs 수정
AppDbContext 클래스에 WorkInstructions DbSet을 추가하여 데이터베이스 모델을 설정합니다.
csharp코드 복사
using Microsoft.EntityFrameworkCore;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
namespace WindowsFormsApp1Core.SQLModels
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<WorkInstruction> WorkInstructions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
string connectionString = "Server=localhost;Database=plc_data_model1;User=root;Password=Alejd1785!;";
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
}
}
}
}
의존성 주입 설정
1. Program.cs 수정
프로젝트의 DI 컨테이너에 **AppDbContext**와 **WorkInstructionService**를 등록합니다.
csharp코드 복사
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.EntityFrameworkCore;
using WindowsFormsApp1Core.SQLModels;
using Microsoft.Extensions.Logging;
namespace WorkManagementSystem
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureServices((context, services) =>
{
services.AddDbContext<AppDbContext>(options =>
options.UseMySql(
context.Configuration.GetConnectionString("DefaultConnection"),
ServerVersion.AutoDetect(context.Configuration.GetConnectionString("DefaultConnection"))
));
services.AddScoped<WorkInstructionService>();
services.AddLogging();
services.AddControllersWithViews();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSyncfusionBlazor();
});
webBuilder.Configure((context, app) =>
{
var env = context.HostingEnvironment;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapRazorPages();
endpoints.MapFallbackToPage("/_Host");
});
});
});
}
}
데이터베이스 마이그레이션 및 업데이트
1. 마이그레이션 실행
Entity Framework Core를 사용하여 데이터베이스 마이그레이션을 실행하여 데이터베이스 스키마를 업데이트합니다.
powershell코드 복사
Add-Migration InitialCreate
Update-Database
2. 데이터베이스 초기화
Update-Database 명령을 실행하여 데이터베이스를 최신 상태로 업데이트합니다. 이를 통해 데이터베이스 스키마가 프로젝트의 모델과 일치하게 됩니다.
결론
이번 포스팅에서는 프로젝트의 백엔드 설정을 위한 의존성 설치와 설정 방법을 다루었습니다. NuGet 패키지를 설치하고, 데이터베이스 연결을 설정하며, DI 컨테이너에 필요한 서비스를 등록하는 과정을 살펴보았습니다. 이러한 설정이 완료되면 프로젝트가 정상적으로 실행되고 데이터베이스와 상호작용할 수 있게 됩니다. 다음 포스팅에서는 프로젝트의 프론트엔드와 관련된 설정 및 구현 사항을 다룰 예정입니다.
5. WorkInstructionService 클래스와 컨트롤러 구현
서론: 이 포스팅에서는 WorkInstructionService 클래스와 이를 사용하는 컨트롤러를 구현하는 방법을 다룹니다. WorkInstructionService 클래스는 작업 지시서의 CRUD 작업을 담당하며, 컨트롤러는 이러한 서비스를 호출하여 클라이언트 요청을 처리합니다.
WorkInstructionService 클래스 구현
WorkInstructionService 클래스는 데이터베이스에서 작업 지시서를 관리하는 비즈니스 로직을 포함합니다.
1. WorkInstructionService.cs
csharp코드 복사
using System.Collections.Generic;
using System.Threading.Tasks;
using WindowsFormsApp1Core.SQLModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.WorkManagementSystem.WMSrvs
{
public class WorkInstructionService
{
private readonly AppDbContext _context;
private readonly ILogger<WorkInstructionService> _logger;
public WorkInstructionService(AppDbContext context, ILogger<WorkInstructionService> logger)
{
_context = context;
_logger = logger;
}
public async Task<IEnumerable<WorkInstruction>> GetWorkInstructionsAsync()
{
try
{
return await _context.WorkInstructions.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
throw;
}
}
public async Task AddWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
_context.WorkInstructions.Add(workInstruction);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
throw;
}
}
public async Task UpdateWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
var existing = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == workInstruction.TaskName);
if (existing != null)
{
existing.Content = workInstruction.Content;
existing.Date = workInstruction.Date;
existing.Writer = workInstruction.Writer;
existing.Priority = workInstruction.Priority;
existing.IsCompleted = workInstruction.IsCompleted;
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", workInstruction.TaskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
throw;
}
}
public async Task DeleteWorkInstructionAsync(string taskName)
{
try
{
var workInstruction = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
if (workInstruction != null)
{
_context.WorkInstructions.Remove(workInstruction);
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", taskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
throw;
}
}
public async Task<WorkInstruction> GetWorkInstructionByTaskNameAsync(string taskName)
{
try
{
return await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instruction by task name");
throw;
}
}
}
}
WorkInstructionController 클래스 구현
컨트롤러는 **WorkInstructionService**를 사용하여 클라이언트 요청을 처리합니다.
2. WorkInstructionController.cs
csharp코드 복사
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMSrvs;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.Dashboard.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class WorkInstructionController : ControllerBase
{
private readonly WorkInstructionService _service;
private readonly ILogger<WorkInstructionController> _logger;
public WorkInstructionController(WorkInstructionService service, ILogger<WorkInstructionController> logger)
{
_service = service;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<WorkInstruction>>> Get()
{
try
{
var workInstructions = await _service.GetWorkInstructionsAsync();
return Ok(workInstructions);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
return StatusCode(500, "Internal server error");
}
}
[HttpPost]
public async Task<ActionResult<WorkInstruction>> Post(WorkInstruction workInstruction)
{
try
{
await _service.AddWorkInstructionAsync(workInstruction);
return CreatedAtAction(nameof(Get), new { id = workInstruction.TaskName }, workInstruction);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpPut("{taskName}")]
public async Task<IActionResult> Put(string taskName, WorkInstruction workInstruction)
{
try
{
var existingWorkInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (existingWorkInstruction == null)
{
return NotFound();
}
await _service.UpdateWorkInstructionAsync(workInstruction);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpDelete("{taskName}")]
public async Task<IActionResult> Delete(string taskName)
{
try
{
var workInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (workInstruction == null)
{
return NotFound();
}
await _service.DeleteWorkInstructionAsync(taskName);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
return StatusCode(500, "Internal server error");
}
}
}
}
결론
이번 포스팅에서는 WorkInstructionService 클래스와 이를 사용하는 컨트롤러를 구현하는 방법을 다루었습니다. WorkInstructionService 클래스는 데이터베이스에서 작업 지시서를 관리하는 비즈니스 로직을 포함하고 있으며, 컨트롤러는 이러한 서비스를 호출하여 클라이언트 요청을 처리합니다. 다음 포스팅에서는 프로젝트의 프론트엔드와 관련된 설정 및 구현 사항을 다룰 예정입니다.
6. 의존성 주입 및 데이터베이스 설정
서론: 이 포스팅에서는 의존성 주입(DI)과 데이터베이스 설정을 다룹니다. DI는 애플리케이션의 구성 요소를 서로 분리하여 유지 관리와 테스트를 용이하게 하고, 데이터베이스 설정은 애플리케이션이 데이터베이스와 상호 작용할 수 있도록 구성하는 중요한 단계입니다.
의존성 주입 설정
의존성 주입은 애플리케이션의 클래스들이 필요한 종속성을 외부에서 주입받도록 하는 패턴입니다. 이를 통해 클래스 간의 결합도를 낮추고 유연성을 높일 수 있습니다.
1. Program.cs
Program.cs 파일에서 서비스와 데이터베이스 컨텍스트를 설정합니다.
csharp코드 복사
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using WindowsFormsApp1Core.SQLModels;
using Syncfusion.Blazor;
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using WindowsFormsApp1Core.WorkManagementSystem.WMSrvs;
namespace WorkManagementSystem
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.SetCompatibleTextRenderingDefault(false);
var host = CreateHostBuilder(args).Build();
host.Start();
Application.Run(new FormMain());
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureServices((context, services) =>
{
services.AddDbContext<AppDbContext>(options =>
options.UseMySql(
context.Configuration.GetConnectionString("DefaultConnection"),
ServerVersion.AutoDetect(context.Configuration.GetConnectionString("DefaultConnection"))
));
// Add WorkInstructionService to the DI container
services.AddScoped<WorkInstructionService>();
services.AddControllersWithViews();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSyncfusionBlazor();
});
webBuilder.Configure((context, app) =>
{
var env = context.HostingEnvironment;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapRazorPages();
endpoints.MapFallbackToPage("/_Host");
});
});
});
}
}
데이터베이스 설정
데이터베이스 설정은 애플리케이션이 데이터베이스와 상호 작용할 수 있도록 구성하는 중요한 단계입니다. 이를 위해 appsettings.json 파일과 AppDbContext 클래스를 설정합니다.
2. appsettings.json
데이터베이스 연결 문자열을 설정합니다.
json코드 복사
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=plc_data_model1;User=root;Password=Alejd1785!;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
3. AppDbContext.cs
AppDbContext 클래스는 데이터베이스와의 연결을 관리합니다.
csharp코드 복사
using Microsoft.EntityFrameworkCore;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
namespace WindowsFormsApp1Core.SQLModels
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<PlcDataModel> PlcDatas { get; set; }
public DbSet<Table1> Table1s { get; set; }
public DbSet<Table2> Table2s { get; set; }
public DbSet<WorkInstruction> WorkInstructions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
string connectionString = "Server=localhost;Database=plc_data_model1;User=root;Password=Alejd1785!;";
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
}
}
}
}
결론
이번 포스팅에서는 의존성 주입과 데이터베이스 설정 방법을 다루었습니다. 의존성 주입을 통해 클래스 간의 결합도를 낮추고 유연성을 높였으며, 데이터베이스 설정을 통해 애플리케이션이 데이터베이스와 원활하게 상호 작용할 수 있도록 구성했습니다. 다음 포스팅에서는 프로젝트의 유닛 테스트와 디버깅 방법에 대해 다룰 예정입니다.
7. 서비스와 컨트롤러 구현
서론: 이번 포스팅에서는 **WorkInstructionService**와 **WorkInstructionController**를 구현하는 과정을 다룹니다. 이 과정은 비즈니스 로직과 API 엔드포인트를 분리하여 코드의 가독성과 유지 보수성을 높이는 중요한 단계입니다.
서비스 클래스 구현
서비스 클래스는 비즈니스 로직을 처리하는 데 사용됩니다. WorkInstructionService 클래스는 데이터베이스와 상호 작용하며, CRUD 작업을 수행합니다.
1. WorkInstructionService 클래스
다음은 WorkInstructionService 클래스의 구현 예제입니다.
csharp코드 복사
using System.Collections.Generic;
using System.Threading.Tasks;
using WindowsFormsApp1Core.SQLModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.WorkManagementSystem.WMSrvs
{
public class WorkInstructionService
{
private readonly AppDbContext _context;
private readonly ILogger<WorkInstructionService> _logger;
public WorkInstructionService(AppDbContext context, ILogger<WorkInstructionService> logger)
{
_context = context;
_logger = logger;
}
public async Task<IEnumerable<WorkInstruction>> GetWorkInstructionsAsync()
{
try
{
return await _context.WorkInstructions.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
throw;
}
}
public async Task AddWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
_context.WorkInstructions.Add(workInstruction);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
throw;
}
}
public async Task UpdateWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
var existing = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == workInstruction.TaskName);
if (existing != null)
{
existing.Content = workInstruction.Content;
existing.Date = workInstruction.Date;
existing.Writer = workInstruction.Writer;
existing.Priority = workInstruction.Priority;
existing.IsCompleted = workInstruction.IsCompleted;
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", workInstruction.TaskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
throw;
}
}
public async Task DeleteWorkInstructionAsync(string taskName)
{
try
{
var workInstruction = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
if (workInstruction != null)
{
_context.WorkInstructions.Remove(workInstruction);
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", taskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
throw;
}
}
public async Task<WorkInstruction> GetWorkInstructionByTaskNameAsync(string taskName)
{
try
{
return await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instruction by task name");
throw;
}
}
}
}
컨트롤러 클래스 구현
컨트롤러 클래스는 HTTP 요청을 처리하고, 서비스 클래스와 상호 작용하여 클라이언트에게 응답을 반환합니다.
2. WorkInstructionController 클래스
다음은 WorkInstructionController 클래스의 구현 예제입니다.
csharp코드 복사
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMSrvs;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.Dashboard.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class WorkInstructionController : ControllerBase
{
private readonly WorkInstructionService _service;
private readonly ILogger<WorkInstructionController> _logger;
public WorkInstructionController(WorkInstructionService service, ILogger<WorkInstructionController> logger)
{
_service = service;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<WorkInstruction>>> Get()
{
try
{
var workInstructions = await _service.GetWorkInstructionsAsync();
return Ok(workInstructions);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
return StatusCode(500, "Internal server error");
}
}
[HttpPost]
public async Task<ActionResult<WorkInstruction>> Post(WorkInstruction workInstruction)
{
try
{
await _service.AddWorkInstructionAsync(workInstruction);
return CreatedAtAction(nameof(Get), new { id = workInstruction.TaskName }, workInstruction);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpPut("{taskName}")]
public async Task<IActionResult> Put(string taskName, WorkInstruction workInstruction)
{
try
{
var existingWorkInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (existingWorkInstruction == null)
{
return NotFound();
}
await _service.UpdateWorkInstructionAsync(workInstruction);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpDelete("{taskName}")]
public async Task<IActionResult> Delete(string taskName)
{
try
{
var workInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (workInstruction == null)
{
return NotFound();
}
await _service.DeleteWorkInstructionAsync(taskName);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
return StatusCode(500, "Internal server error");
}
}
}
}
결론
이번 포스팅에서는 **WorkInstructionService**와 **WorkInstructionController**의 구현 과정을 다루었습니다. 서비스 클래스는 데이터베이스와 상호 작용하며, 컨트롤러 클래스는 HTTP 요청을 처리하고 서비스를 호출하여 클라이언트에게 응답을 반환합니다. 다음 포스팅에서는 프로젝트의 유닛 테스트와 디버깅 방법에 대해 다룰 예정입니다.
8. 의존성 주입 설정 및 데이터베이스 연결
서론: 이번 포스팅에서는 **WorkInstructionService**와 **AppDbContext**를 프로젝트에 의존성 주입(DI)하여 설정하고 데이터베이스와의 연결을 설정하는 방법을 다룹니다. 올바른 DI 설정은 코드의 모듈화와 테스트 가능성을 높이는 중요한 단계입니다.
의존성 주입 설정
의존성 주입은 객체 간의 의존성을 설정하는 디자인 패턴으로, 객체 생성과 라이프사이클 관리를 프레임워크에 맡기는 방식입니다. 이를 통해 코드의 결합도를 낮추고 테스트 가능성을 높일 수 있습니다.
1. Program.cs 파일 설정
Program.cs 파일에서 서비스와 DbContext를 DI 컨테이너에 등록해야 합니다. 이를 위해 CreateHostBuilder 메서드에서 필요한 서비스를 추가합니다.
csharp코드 복사
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.EntityFrameworkCore;
using WindowsFormsApp1Core.SQLModels;
using Syncfusion.Blazor;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using WindowsFormsApp1Core.WorkManagementSystem.WMSrvs;
namespace WorkManagementSystem
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.SetCompatibleTextRenderingDefault(false);
var host = CreateHostBuilder(args).Build();
host.Start();
Application.Run(new FormMain());
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureServices((context, services) =>
{
services.AddDbContext<AppDbContext>(options =>
options.UseMySql(
context.Configuration.GetConnectionString("DefaultConnection"),
ServerVersion.AutoDetect(context.Configuration.GetConnectionString("DefaultConnection"))
));
services.AddScoped<WorkInstructionService>();
services.AddControllersWithViews();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSyncfusionBlazor();
});
webBuilder.Configure((context, app) =>
{
var env = context.HostingEnvironment;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapRazorPages();
endpoints.MapFallbackToPage("/_Host");
});
});
});
}
}
데이터베이스 연결 설정
2. appsettings.json 파일 설정
데이터베이스 연결 문자열은 appsettings.json 파일에 저장됩니다. 이를 통해 데이터베이스와의 연결 정보를 관리할 수 있습니다.
json코드 복사
{
"ConnectionStrings": {
"DefaultConnection": "Server=localhost;Database=plc_data_model1;User=root;Password=Alejd1785!;"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}
DbContext 설정
3. AppDbContext 클래스 설정
AppDbContext 클래스는 Entity Framework Core를 사용하여 데이터베이스와 상호 작용하는 클래스입니다. 여기서는 필요한 DbSet을 정의하고, 연결 문자열을 설정합니다.
csharp코드 복사
using Microsoft.EntityFrameworkCore;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
namespace WindowsFormsApp1Core.SQLModels
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<PlcDataModel> PlcDatas { get; set; }
public DbSet<Table1> Table1s { get; set; }
public DbSet<Table2> Table2s { get; set; }
public DbSet<WorkInstruction> WorkInstructions { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
string connectionString = "Server=localhost;Database=plc_data_model1;User=root;Password=Alejd1785!;";
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
}
}
}
}
결론
이번 포스팅에서는 **WorkInstructionService**와 **AppDbContext**를 DI 컨테이너에 등록하고, 데이터베이스와의 연결을 설정하는 방법을 다루었습니다. 이를 통해 서비스와 데이터베이스 간의 상호 작용을 원활하게 하였으며, 의존성 주입을 통해 코드의 모듈화와 테스트 가능성을 높였습니다. 다음 포스팅에서는 프로젝트의 유닛 테스트와 디버깅 방법에 대해 다룰 예정입니다.
9. 서비스 및 컨트롤러 구현
서론: 이번 포스팅에서는 **WorkInstructionService**와 **WorkInstructionController**의 구체적인 구현 방법을 다루겠습니다. 이를 통해 작업 지시서를 생성, 읽기, 업데이트, 삭제(CRUD)하는 기능을 제공하고, 각 메서드가 어떻게 동작하는지 설명하겠습니다.
서비스 구현
WorkInstructionService 클래스는 **AppDbContext**를 통해 데이터베이스와 상호 작용하며, 작업 지시서의 CRUD 작업을 처리합니다. 이 클래스는 컨트롤러에서 호출되어 작업 지시서 관련 기능을 제공합니다.
1. WorkInstructionService 클래스
csharp코드 복사
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WindowsFormsApp1Core.SQLModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.WorkManagementSystem.WMSrvs
{
public class WorkInstructionService
{
private readonly AppDbContext _context;
private readonly ILogger<WorkInstructionService> _logger;
public WorkInstructionService(AppDbContext context, ILogger<WorkInstructionService> logger)
{
_context = context;
_logger = logger;
}
public async Task<IEnumerable<WorkInstruction>> GetWorkInstructionsAsync()
{
try
{
return await _context.WorkInstructions.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
throw;
}
}
public async Task AddWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
_context.WorkInstructions.Add(workInstruction);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
throw;
}
}
public async Task UpdateWorkInstructionAsync(WorkInstruction workInstruction)
{
try
{
var existing = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == workInstruction.TaskName);
if (existing != null)
{
existing.Content = workInstruction.Content;
existing.Date = workInstruction.Date;
existing.Writer = workInstruction.Writer;
existing.Priority = workInstruction.Priority;
existing.IsCompleted = workInstruction.IsCompleted;
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", workInstruction.TaskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
throw;
}
}
public async Task DeleteWorkInstructionAsync(string taskName)
{
try
{
var workInstruction = await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
if (workInstruction != null)
{
_context.WorkInstructions.Remove(workInstruction);
await _context.SaveChangesAsync();
}
else
{
_logger.LogWarning("Work instruction not found: {TaskName}", taskName);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
throw;
}
}
public async Task<WorkInstruction> GetWorkInstructionByTaskNameAsync(string taskName)
{
try
{
return await _context.WorkInstructions.FirstOrDefaultAsync(w => w.TaskName == taskName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instruction by task name");
throw;
}
}
}
}
컨트롤러 구현
WorkInstructionController 클래스는 API 엔드포인트를 제공하며, 서비스 클래스를 통해 작업 지시서의 CRUD 작업을 처리합니다. 각 메서드는 HTTP 요청을 처리하고, 적절한 응답을 반환합니다.
2. WorkInstructionController 클래스
csharp코드 복사
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using WindowsFormsApp1Core.WorkManagementSystem.WMModels;
using WindowsFormsApp1Core.WorkManagementSystem.WMSrvs;
using Microsoft.Extensions.Logging;
namespace WindowsFormsApp1Core.Dashboard.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class WorkInstructionController : ControllerBase
{
private readonly WorkInstructionService _service;
private readonly ILogger<WorkInstructionController> _logger;
public WorkInstructionController(WorkInstructionService service, ILogger<WorkInstructionController> logger)
{
_service = service;
_logger = logger;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<WorkInstruction>>> Get()
{
try
{
var workInstructions = await _service.GetWorkInstructionsAsync();
return Ok(workInstructions);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error fetching work instructions");
return StatusCode(500, "Internal server error");
}
}
[HttpPost]
public async Task<ActionResult<WorkInstruction>> Post(WorkInstruction workInstruction)
{
try
{
await _service.AddWorkInstructionAsync(workInstruction);
return CreatedAtAction(nameof(Get), new { id = workInstruction.TaskName }, workInstruction);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error adding work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpPut("{taskName}")]
public async Task<IActionResult> Put(string taskName, WorkInstruction workInstruction)
{
try
{
var existingWorkInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (existingWorkInstruction == null)
{
return NotFound();
}
await _service.UpdateWorkInstructionAsync(workInstruction);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error updating work instruction");
return StatusCode(500, "Internal server error");
}
}
[HttpDelete("{taskName}")]
public async Task<IActionResult> Delete(string taskName)
{
try
{
var workInstruction = await _service.GetWorkInstructionByTaskNameAsync(taskName);
if (workInstruction == null)
{
return NotFound();
}
await _service.DeleteWorkInstructionAsync(taskName);
return NoContent();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error deleting work instruction");
return StatusCode(500, "Internal server error");
}
}
}
}
결론
이번 포스팅에서는 **WorkInstructionService**와 **WorkInstructionController**의 구현을 통해 작업 지시서의 CRUD 기능을 제공하는 방법을 다루었습니다. 이를 통해 프로젝트의 핵심 기능을 구현하고, 올바른 DI 설정과 서비스-컨트롤러 구조를 이해할 수 있었습니다. 다음 포스팅에서는 프로젝트의 유닛 테스트와 디버깅 방법에 대해 다룰 예정입니다.
'Development👩🏻🦳 > C#' 카테고리의 다른 글
| C# mes 프로젝트 백엔드 구현 정리 및 추가 가이드 ( -3- ) (0) | 2024.07.06 |
|---|---|
| C# mes 프로젝트 백엔드 구현 정리 및 추가 가이드 ( -2- ) (2) | 2024.07.06 |
| winDowsForms App + plc 통합 생산 및 품질 관리 시스템 프로젝트 시작 (0) | 2024.06.21 |
| Arduino와 브레드보드로 시작하는 전자공학 기초: 프로그래밍 전에 필요한 워밍업 (1) | 2024.06.14 |
| Mitsubishi PLC와 C# WinForms 연동 가이드 ( Guide to Integrating Mitsubishi PLC with C# WinForms ) (0) | 2024.06.14 |