
سرویسهای حرفهای برای روابط چند به چند در EF Core
در این آموزش به سرویسهای حرفهای برای روابط چند به چند در EF Core میپردازیم. ابتدا نحوه پیادهسازی لایه سرویس در EF Core برای مدیریت روابط دانشجو-درس در ASP.NET Core را یاد میگیرید. همچنین، این راهنما شامل عملیات CRUD و مدیریت روابط چند به چند است.
در این آموزش، به بررسی سرویس StudentCourseService میپردازیم. ابتدا این سرویس با استفاده از ابزارهایی مانند AutoMapper، فرایندهای CRUD را سادهسازی میکند. علاوه بر این، سرویس StudentCourseService با ارائه متدهای استاندارد برای مدیریت روابط دانشجو-درس، فرایند توسعه را آسانتر میکند. در نتیجه، با بهکارگیری EF Core و AutoMapper، این سرویس هم عملکرد بهینه و هم خوانایی کد را تضمین میکند.
ساخت اینترفیس جدول واسط – IStudentCourseService
public interface IStudentCourseService
{
Task AddStudentToCourseAsync(int studentId, int courseId);
Task RemoveStudentFromCourseAsync(int studentId, int courseId);
Task<bool> IsStudentEnrolledAsync(int studentId, int courseId);
Task<List<CourseViewModel>> GetCoursesByStudentAsync(int studentId);
Task<List<StudentViewModel>> GetStudentsByCourseAsync(int courseId);
Task<List<StudentViewModel>> GetStudentsNotInCourseAsync(int courseId);
Task<List<CourseViewModel>> GetCoursesNotInStudentsAsync(int studentId);
}- ابتدا ثبتنام دانشجو در یک دوره با استفاده از AddStudentToCourseAsync انجام میشود.
- سپس لغو ثبتنام دانشجو از دوره با RemoveStudentFromCourseAsync انجام میشود.
- همچنین، وجود رابطه ثبتنام با IsStudentEnrolledAsync بررسی میشود.
- علاوه بر این، دورههای یک دانشجو با GetCoursesByStudentAsync دریافت میشوند.
- از طرف دیگر، دانشجویان یک دوره با GetStudentsByCourseAsync دریافت میشوند.
- برای مثال، دانشجویان خارج از یک دوره با GetStudentsNotInCourseAsync دریافت میشوند.
- در نهایت، دورههای بدون ثبتنام دانشجو با GetCoursesNotInStudentsAsync دریافت میشوند.
پیادهسازی سرویس StudentCourseService
- ابتدا دانشجو در یک درس ثبتنام میشود؛ البته این عملیات تنها در صورتی انجام میشود که ثبتنام قبلاً وجود نداشته باشد.
public async Task AddStudentToCourseAsync(int studentId, int courseId)
{
bool exists = await _context.StudentCourses
.AnyAsync(sc => sc.StudentId == studentId && sc.CourseId == courseId);
if (!exists)
{
var student = await _context.students.FirstOrDefaultAsync(s => s.Id == studentId);
var course = await _context.courses.FirstOrDefaultAsync(c => c.Id == courseId);
if (student == null || course == null)
throw new InvalidOperationException("Student or Course not found.");
var studentCourse = new StudentCourse
{
StudentId = studentId,
CourseId = courseId,
Student = student,
Course = course
};
_context.StudentCourses.Add(studentCourse);
await _context.SaveChangesAsync();
}
}- سپس، در صورت وجود رابطه، ثبتنام دانشجو از درس حذف میشود.
public async Task RemoveStudentFromCourseAsync(int studentId, int courseId)
{
var relation = await _context.StudentCourses
.FirstOrDefaultAsync(sc => sc.StudentId == studentId && sc.CourseId == courseId);
if (relation != null)
{
_context.StudentCourses.Remove(relation);
await _context.SaveChangesAsync();
}
}- همچنین، وضعیت ثبتنام دانشجو پیش از انجام عملیات بررسی میشود.
public async Task<bool> IsStudentEnrolledAsync(int studentId, int courseId)
{
return await _context.StudentCourses
.AnyAsync(sc => sc.StudentId == studentId && sc.CourseId == courseId);
}- علاوه بر این، لیست درسهای انتخابشده یک دانشجوی خاص دریافت میشود.
public async Task<List<CourseViewModel>> GetCoursesByStudentAsync(int studentId)
{
return await _context.StudentCourses
.Where(sc => sc.StudentId == studentId)
.Select(sc => sc.Course)
.AsNoTracking()
.ProjectTo<CourseViewModel>(_mapper.ConfigurationProvider)
.ToListAsync();
}- از طرف دیگر، میتوان لیست دانشجویان یک درس خاص را دریافت کرد.
public async Task<List<StudentViewModel>> GetStudentsByCourseAsync(int courseId)
{
return await _context.StudentCourses
.Where(sc => sc.CourseId == courseId)
.Select(sc => sc.Student)
.AsNoTracking()
.ProjectTo<StudentViewModel>(_mapper.ConfigurationProvider)
.ToListAsync();
}- برای مثال، این متد لیست دانشجویانی را دریافت میکند که یک درس خاص را انتخاب نکردهاند.
public async Task<List<StudentViewModel>> GetStudentsNotInCourseAsync(int courseId)
{
return await _context.students
.Where(s => !(s.StudentCourses != null && s.StudentCourses.Any(sc => sc.CourseId == courseId)))
.AsNoTracking()
.ProjectTo<StudentViewModel>(_mapper.ConfigurationProvider)
.ToListAsync();
}- در نهایت، این متد لیست درسهای انتخابنشده یک دانشجوی خاص را دریافت میکند.
public async Task<List<CourseViewModel>> GetCoursesNotInStudentsAsync(int studentId)
{
return await _context.courses
.Where(s => !(s.StudentCourses != null && s.StudentCourses.Any(sc => sc.StudentId == studentId)))
.AsNoTracking()
.ProjectTo<CourseViewModel>(_mapper.ConfigurationProvider)
.ToListAsync();
}ویژگیهای کلیدی StudentCourseService
- عملیات ناهمزمان: ابتدا با استفاده از async/await، عملیات پایگاه داده بدون مسدود کردن برنامه انجام میشود.
- مدیریت روابط چند به چند: همچنین، موجودیت واسط StudentCourse برای مدیریت رابطهها در EF Core استفاده میشود.
- انتساب خودکار با AutoMapper: علاوه بر این، موجودیتها بهسادگی به مدلهای نمایشی یا ViewModel تبدیل میشوند.
چرا از این سرویس استفاده کنیم؟
- مقیاسپذیری: در نتیجه، این سرویس برای برنامههایی با حجم بالای اطلاعات مناسب است.
- کدنویسی تمیز: به همین دلیل، منطق کسبوکار از بخش دسترسی به دادهها جدا میشود.
































فرم افزودن دیدگاه
با ارسال نظرات خود ما را در ایجاد محتوای بهتر کمک کنید.