
آموزش پیشرفته Fluent Api در EF Core
Fluent API یکی از روشهای پیکربندی مدلها در Entity Framework Core است که به صورت کدنویسی زنجیرهای (Fluent Style) در متد OnModelCreating در کلاس DbContext انجام میشود. این روش در کنار Data Annotations استفاده میشود، اما نسبت به آن انعطافپذیرتر و قدرتمندتر است، مخصوصاً برای پیکربندیهای پیچیده مانند روابط چندگانه، Mapping کلید مرکب، تغییر نام جدول/ستون، و غیره. با ما همراه باشید با آموزش پیشرفته Fluent Api در EF Core و Asp.Net Core.
نکات مهم درباره Fluent Api
Fluent API یکی از کاملترین روشها برای پیکربندی مدلها و روابط در EF Core است. در صورت وجود تنظیمات یکسان یا متناقض، تنظیمات Fluent API نسبت به Data Annotation اولویت دارد. بنابراین، تنظیماتی که با Fluent API تعریف شدهاند، تنظیمات مشابه در Data Annotation را بازنویسی میکنند. استفاده ترکیبی از Fluent API و Data Annotation نیز امکانپذیر است. برای مثال، میتوان تنظیمات ساده مانند اجباری بودن یک ویژگی یا محدودیت طول آن را با Data Annotation تعریف کرد. همچنین، تنظیمات پیچیدهتر مانند کلیدهای ترکیبی، روابط بین موجودیتها، رفتار حذف، ایندکسها و نام جدولها را میتوان با Fluent API انجام داد.
در پروژههای حرفهای و ساختارمند، توصیه میشود تنظیمات Fluent API در کلاسهای مجزا قرار گیرند. برای این کار، هر کلاس پیکربندی میتواند اینترفیس را پیادهسازی کند. در نتیجه، کلاس DbContext خلوتتر میشود و تنظیمات هر موجودیت نیز بهصورت جداگانه مدیریت میشوند. علاوه بر این، جداسازی تنظیمات باعث افزایش خوانایی، نگهداری آسانتر و کاهش پیچیدگی کد میشود. به همین دلیل، با افزایش تعداد موجودیتها، پیدا کردن و تغییر تنظیمات مربوط به هر مدل سادهتر خواهد بود.
- استفاده از Fluent API همیشه نسبت به Data Annotations اولویت دارد.
- استفاده ترکیبی از هر دو روش نیز امکانپذیر است.
- در پروژههای حرفهای و ساختارمند، توصیه میشود از Fluent API در کلاسهای مجزا مانند EntityTypeConfiguration استفاده شود.
پرکاربردترین کدهای Fluent API
| قابلیت | کد Fluent API |
|---|---|
| تعریف کلید اصلی | builder.HasKey(x => x.Id); |
| کلید مرکب | builder.HasKey(x => new { x.A, x.B }); |
| تغییر نام جدول | builder.ToTable(“table_name”); |
| تعیین اسکیمای جدول | builder.ToTable(“table_name”, “schema”); |
| تغییر نام ستون | builder.Property(x => x.Email).HasColumnName(“user_email”); |
| تعیین نوع ستون در SQL | builder.Property(x => x.Name).HasColumnType(“nvarchar(100)”); |
| فیلد اجباری | builder.Property(x => x.Name).IsRequired(); |
| طول حداکثری رشته | builder.Property(x => x.Name).HasMaxLength(100); |
| مقدار پیشفرض | builder.Property(x => x.IsActive).HasDefaultValue(true); |
| مقدار پیشفرض با SQL | builder.Property(x => x.CreatedAt).HasDefaultValueSql(“GETDATE()”); |
| نادیده گرفتن ستون | builder.Ignore(x => x.Temp); |
| ستون Auto-Increment | builder.Property(x => x.Id).UseIdentityColumn(); |
| مقدار غیر خودکار | builder.Property(x => x.Id).ValueGeneratedNever(); |
| ستون GUID | builder.Property(x => x.Id).HasDefaultValueSql(“NEWID()”); |
| ستون RowVersion | builder.Property(x => x.RowVersion).IsRowVersion(); |
| ایندکس | builder.HasIndex(x => x.Email); |
| ایندکس یکتا | builder.HasIndex(x => x.Email).IsUnique(); |
| رابطه One-to-Many | builder.HasOne(x => x.Blog) .WithMany(b => b.Posts) .HasForeignKey(x => x.BlogId); |
| رابطه One-to-One | builder.HasOne(x => x.Profile) .WithOne(p => p.User) .HasForeignKey<Profile>(p => p.UserId); |
| رابطه Many-to-Many | builder.HasMany(x => x.Roles) .WithMany(r => r.Users) .UsingEntity(j => j.ToTable(“UserRoles”)); |
مثال عملی Fluent API
- مدل Teacher
public class Teacher
{
public int Id { get; set; }
public required string FullName { get; set; }
public string? Email { get; set; }
public string? Phone { get; set; }
public DateTime HireDate { get; set; }
public bool IsActive { get; set; }
public required string NationalCode { get; set; }
public byte[] RowVersion { get; set; } = default!;
}- کانفیگ مدل Teacher
public void Configure(EntityTypeBuilder<Teacher> builder)
{
// تغییر نام جدول و اسکیمای آن
builder.ToTable("tbl_teachers", "hr");
// تعریف کلید اصلی با Identity (افزایشی خودکار)
builder.HasKey(t => t.Id);
builder.Property(t => t.Id)
.UseIdentityColumn() // ستون به صورت IDENTITY در SQL Server
.ValueGeneratedOnAdd();
// نام و نام خانوادگی (اجباری + حداکثر طول)
builder.Property(t => t.FullName)
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
// ایمیل (اختیاری + محدودیت طول)
builder.Property(t => t.Email)
.HasMaxLength(150)
.HasColumnType("nvarchar(150)");
// شماره تلفن (اختیاری + طول مشخص)
builder.Property(t => t.Phone)
.HasColumnType("nvarchar(11)");
// تاریخ استخدام (مقدار پیشفرض از SQL)
builder.Property(t => t.HireDate)
.HasColumnType("date")
.HasDefaultValueSql("GETDATE()");
// فعال بودن (مقدار پیشفرض false)
builder.Property(t => t.IsActive)
.HasDefaultValue(false);
// کد ملی (الزامی + یکتا)
builder.Property(t => t.NationalCode)
.IsRequired()
.HasMaxLength(10);
// ایندکس یکتا برای کد ملی
builder.HasIndex(t => t.NationalCode)
.IsUnique();
// تنظیم نسخه برای کنترل همزمانی
builder.Property(t => t.RowVersion)
.IsRowVersion();
}پیکربندی تمیز مدلها با IEntityTypeConfiguration
IEntityTypeConfiguration یک اینترفیس از EF Core است که امکان میدهد پیکربندی هر مدل را در فایل جداگانه و تخصصی انجام دهیم. این الگو باعث میشود کلاس DbContext بسیار تمیزتر و قابل نگهداریتر شود و اصل مسئولیت یگانه (SRP) در معماری رعایت شود.
بهترین مسیر برای ساخت IEntityTypeConfiguration
بهترین مسیر برای ساخت IEntityTypeConfiguration داخل فولدر Database Contex است. در پوشه Database Context یک پوشه جدید با نام Configurations ایجاد میکنیم. و داخل آن میتوانیم فایلهای Config خود را اضافه کنیم. نام کانفیگ ها باید ترکیبی از ModelName + Configuration باشد. این ساختار اجباری نیست. ولی حرفه ای است.
ساخت کلاس پیکربندی جداگانه
- کلاسی که میسازیم باید از IEntityTypeConfiguration<ModelName> ارث بری کند.
- نیاز است متد های IEntityTypeConfiguration حتما Implement شوند.
- در این مثال نام مدل ما UserProfile میباشد.
public class UserProfileConfiguration : IEntityTypeConfiguration<UserProfile>
{
public void Configure(EntityTypeBuilder<UserProfile> builder)
{
//Config
}
}رجیستر کردن در DbContext
حالا باید این پیکربندی را در OnModelCreating داخل DbContext رجیستر کنیم.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// اعمال پیکربندی با استفاده از کلاس جداگانه
modelBuilder.ApplyConfiguration(new UserProfileConfiguration());
}
































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