اجرای فرآیندهای ذخیره شده هسته پیچیده موجودیت چارچوب


توسعه دهندگان دات نت اغلب نیاز به فراخوانی رویه ذخیره شده پایگاه داده (SP) از لایه سرور C# خود دارند. مایکروسافت هسته چارچوب نهاد (EF). می تواند برای نقشه برداری یا وارد کردن SP ها به عنوان توابع استفاده شود، اما، متأسفانه، EF Core به طور بومی از بازیابی نتایج پیچیده از رویه های ذخیره شده پشتیبانی نمی کند. این به دلیل محدودیت‌های موجود در راه‌حل خارج از جعبه EF Core است که:

  • نتیجه یک رویه ذخیره شده را به یک محدود کنید Entity نوع
  • نمی توان یک نوع پیچیده را در پاسخ به a برگرداند JOIN فرمان
  • عملیات ایجاد، به‌روزرسانی و حذف را غیرقابل دسترس کنید.

ما می توانیم با استفاده از C#، .NET، Microsoft SQL Server و EF Core این محدودیت ها را دور بزنیم. این راه حل را می توان با هر پایگاه داده با پشتیبانی دات نت یا زبان دات نت که از EF Core پشتیبانی می کند استفاده کرد، مشروط بر اینکه کد ابزار به آن زبان ترجمه شده باشد. ما به یک نمونه رویه ذخیره شده نگاه می کنیم تا ببینیم چگونه چند تنظیم ساده می تواند بر محدودیت های EF Core غلبه کند.

یک روش ذخیره شده فرضی با یک نتیجه پیچیده

در نظر بگیریم GetEmployeesWithDepartment، یک رویه ذخیره شده که یک نتیجه پیچیده حاوی اطلاعات از دو جدول پایگاه داده مرتبط را برمی گرداند، Employee و Department:

دو جدول پایگاه داده مرتبط که از آنها یک رویه ذخیره شده که یک نتیجه پیچیده حاوی اطلاعات را برمی گرداند می تواند از آن ها بیاید.

این Employee جدول خود را از طریق a ارجاع می دهد کلید خارجی از آن ManagerId رشته. همچنین به Department جدول از Employee.DepartmentId فیلد متصل به Department جدول Id ستون روابط ترتیبی بین این جداول عبارتند از:

Relationships = Employee(1) : Department(1) and Department(1) : Employees(N)

حالا بیایید نگاه کنیم GetEmployeesWithDepartment، یک SP که an را برمی گرداند Employee ردیف جدول مطابق با پارامتر ورودی Employee.Id. SP ما را برمی گرداند Id ارزش و تمام اطلاعات مرتبط با آن، مانند کارمند Department و Name ارزش های:

CREATE OR ALTER PROCEDURE [dbo].[GetEmployeesWithDepartment] 	
    @id INT
AS
BEGIN
    SET NOCOUNT ON;

    SELECT [E].*, [D].[Name] AS [Department]
    FROM [dbo].[Employee] [E]
        INNER JOIN [dbo].[Department] [D] ON [E].[DepartmentId] = [D].[Id]
    WHERE [E].[Id] >= @id
END

فرض کنید می‌خواهیم بخش مرتبط با اولین کارمند فهرست شده در a را تعیین کنیم پایگاه داده تست ساده (در مثال ما، اولین کارمند لیست شده جان در مهندسی است). ما می خواهیم این SP را از کد C# خود اجرا کنیم، بنابراین اجازه دهید EF Core را برای پشتیبانی از تماس پیکربندی کنیم. GetEmployeesWithDepartment به عنوان یک SP پارامتر شده.

توجه: قبل از ادامه، پایگاه داده خود را داربست کنید با استفاده از Scaffold-DbContext دستور در کنسول Package Manager یا dotnet ef dbcontext scaffold دستور در NET Core CLI.

مرحله 1: یک مدل مجموعه نتایج ذخیره شده رویه ایجاد کنید

ابتدا یک فایل به نام ایجاد می کنیم GetEmployeesWithDepartment_Result.cs و ساختار را برای نوع بازگشت پیچیده ما تعریف کنید:

public class GetEmployeesWithDepartment_Result
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int DepartmentId { get; set; }
    public int? ManagerId { get; set; }
    public int Salary { get; set; }
    public decimal? Bonus { get; set; }
    public string Department { get; set; }
}

با استفاده از Microsoft SQL Server به عنوان سرور پایگاه داده، می‌توانیم به طور صریح انواع ستون‌های نتیجه SP را با اجرای sp_describe_first_result_set دستور:

EXEC sp_describe_first_result_set N'[dbo].[GetEmployeesWithDepartment]'

این دستور نشان می دهد ستون های رویه ذخیره شده و لیست انواع مرتبط با تعریف نوع نتیجه، ما به سمت به روز رسانی خود حرکت می کنیم مدل EF.

مرحله 2: شامل مدل در DbContext فایل

ما آماده هستیم تا مدل نتیجه را در هسته EF برنامه خود بگنجانیم DbContext فایل. EF یک رویکرد ظریف برای گسترش مدل داده یک برنامه ارائه می دهد. چنین یک برنامه افزودنی پشتیبانی می شود با کلاس های جزئی و – به طور خاص – با استفاده از یک OnModelCreatingPartial روش. برای اینکه ابزارهای داربست EF Core کد سفارشی ما را تغییر ندهند، مدل نتیجه خود را به EFCoreSPContext.SP.cs، یک کلاس C# جزئی:

using EFCoreSP.Data.SPs;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;

namespace EFCoreSP.Data
{
    public partial class EFCoreSPContext : DbContext
    {
        public virtual DbSet<GetEmployeesWithDepartment_Result>
            GetEmployeesWithDepartment_Results { get; set; }

        // We’ll add subsequent changes here
    }
}

در اینجا چگونه است EFCoreSPContext.SP.cs به داخل نگاه می کند مخزن ما. اکنون باید کدی را اضافه کنیم که کلید اصلی مدل ما را مشخص کند، در صورت وجود.

مرحله 3: کلید مدل را مشخص کنید

با پیکربندی مدل خود در یک نشان می‌دهیم که آیا مجموعه نتایج SP ما یک مقدار کلیدی دارد یا خیر OnModelCreatingPartial روش در ما EFCoreSPContext تعریف.

اگر مجموعه نتایج ما دارای یک مقدار کلیدی باشد، از آن استفاده می کنیم HasKey روشی برای شناسایی صریح ویژگی مرتبط با آن مقدار کلیدی:

partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<GetEmployeesWithDepartment_Result>(entity => 
        entity.HasKey(e => e.Id));      
}

اگر موجودیت ما هیچ مقدار کلیدی نداشته باشد، از آن استفاده می کنیم HasNoKey روش در عوض:

partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<GetEmployeesWithDepartment_Result>(entity => 
        entity.HasNoKey());       
}

تعریف مدل ما اکنون کامل شده است. ما آماده ایم با SP تماس گرفته و داده های کارمند نمونه خود را بازیابی کنیم.

فراخوانی مراحل ذخیره شده پیچیده: آسان به عنوان 1-2-3

برای ساده کردن فراخوانی SP خود، یک روش عمومی دیگر را به آن اضافه می کنیم EFCoreSPContext فایل. تعریف روش این را می پذیرد Employee.Id ارزش ارائه شده، از آن عبور می کند Id به SP، و نتایج پیچیده تولید شده را به عنوان یک لیست بازیابی می کند:

public IEnumerable<GetEmployeesWithDepartment_Result> 
    SP_GetEmployeesWithDepartment(int id)
{
    return this.GetEmployeesWithDepartment_Results
        .FromSqlInterpolated($"[dbo].[GetEmployeesWithDepartment] {id}")
        .ToArray();
}

ما DbContext فایل اکنون آماده فراخوانی یک رویه ذخیره شده و برگرداندن یک مجموعه نتیجه نوع پیچیده است و ما کد کامل است. با بازگشت به پرس و جوی مثال خود، می توانیم از یک دستور ساده برای برگرداندن بخش و سایر داده های مرتبط با اولین کارمند در پایگاه داده خود استفاده کنیم:

var employees = dbContext.SP_GetEmployeesWithDepartment(1);

ما یک راه حل ساده و در عین حال هوشمندانه و قدرتمند را برای بازگرداندن یک موجودیت غیر پایگاه داده از رویه ذخیره شده اعمال کردیم. این رویکرد مستلزم خطوط نسبتا کمی از کد پشتیبانی است و هنگام استفاده از EF Core برای بازیابی نتایج پیچیده، سود قابل توجهی را به همراه دارد.

تیم تحریریه وبلاگ مهندسی تاپتال از شما تشکر می کند الکساندر اسکوگورف برای بررسی محتوای فنی و نمونه کد ارائه شده در این مقاله.


ادامه مطلب در وبلاگ مهندسی تاپتال:




منبع

Matthew Newman

Matthew Newman Matthew has over 15 years of experience in database management and software development, with a strong focus on full-stack web applications. He specializes in Django and Vue.js with expertise deploying to both server and serverless environments on AWS. He also works with relational databases and large datasets
[ Back To Top ]