بر اساس توضیح سایت Wikipedia، مفهوم Fluent API یا Fluent Interface به معنی پیاده سازی API شی گرا می باشد که قابلیت خوانایی آن را افزایش می دهد. اما اینکه این فلوئنت در Code First چه کاری انجام میدهد؟ شما می توانید دستور های Mapping را به صورتی بنویسید که قابلیت خوانایی و درک آن بالاتر برود.

برای تعریف Mapping با کمک Fluent API می توان به دو صورت عمل کرد:

  1. نوشتن دستورات در متد OnModelCreating
  2. ایجاد یک کلاس جداگانه برای Map و اضافه کردن آن به کلاس Context

برای استفاده مورد اول، متد OnModelCreating را که یک متد virtual هست، در کلاس Context باید Override کنیم، پارامتر این متد یک شئ از نوع DbModelBuilder هست. بوسیله متد های این شئ ما می توانیم عملیات Mapping را انجام دهیم. در ادامه به بررسی متد های زیر از شئ DbModelBuilder می پردازیم:

 

  • متد Entity
  • متد ToTable
  • متد Property
  • متد HasColumnName
  • متد HasColumnType
  • متد HasDatabaseGeneratedOption
  • متدهای IsRequired و IsOptional
  • متد IsMaxLength
  • متد HasMaxLength
  • متد HasKey
  • متد Ignore

 

[icon icon="fa-suitcase"]  متد Entity

در حقیقت این متد انتخاب کننده کلاسی هست که می خواهیم عملیات Mapping را برای آن انجام دهیم، نوع جنریک این متد باید از نوع کلاسی باشد که عملیات Mapping برای آن انجام می شود، نوع برگشتی این متد از نوع EntityTypeConfiguration است که بوسیله متد های آن می توانیم عملیات Mapping مربوط به آن Entity را انجام دهیم.

[icon icon="fa-suitcase"]  متد ToTable

این متد که در کلاس EntityTypeConfiguration تعریف شده است، تعیین کننده جدول معادل کلاس در بانک اطلاعاتی است:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Customer>().ToTable("MyTable");
}

  Attribute معادل: TableAttribute  

[icon icon="fa-suitcase"]   متد Property

برای تغییر Mapping یک خصوصیت، از این متد استفاده می کنیم، در این حقیقت این متد Selector خصوصیت می باشد و نوع برگشتی آن بر اساس نوع خصوصیت انتخابی فرق می کند. برای مثال با انتخاب یک خصوصیت از نوع رشته، نوع برگشتی این متد از نوع StringPropertyConfigurator یا برای خصوصیات از نوع عددی از نوع PrimitivePropertyConfigurator می باشد. برای مثال، انتخاب خصوصیت FirstName از کلاس Customer:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Customer>().Property(customer => customer.FirstName)
}

 

 [icon icon="fa-suitcase"]  متد HasColumnName

بوسیله این متد می توان نام ستون معادل یک خصوصیت را بانک اطلاعاتی مشخص کرد، برای مثال، در زیر خصوصیت FirstName به ستون FName و خصوصیت LastName به ستون LName اشاره خواهد کرد:

modelBuilder.Entity<Customer>().Property(customer => customer.FirstName).HasColumnName("FName");
modelBuilder.Entity<Customer>().Property(customer => customer.LastName).HasColumnName("LName");

  Attribute معادل: ColumnAttribute  

[icon icon="fa-suitcase"]  متد HasColumnName

بوسیله این متد می توان نوع ستون معادل خصوصیت انتخاب شده در بانک اطلاعاتی را مشخص کرد

modelBuilder.Entity<Customer>().Property(customer => customer.FirstName).HasColumnType("varchar");

  Attribute معادل: ColumnAttribute  

[icon icon="fa-suitcase"]  متد HasDatabaseGeneratedOption

اگر ستون معادل خصوصیت انتخابی در بانک، از نوع Identity یا Computed باشد، بوسیله این متد می توان این مورد را به Entity Framework شناساند:

modelBuilder.Entity<Customer>().Property(customer => customer.CustomerID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

   

[icon icon="fa-suitcase"]  متد های IsRequired و IsOptional

بوسیله این دو متد می توان نوع ستون را که مقدار Null قبول می کند یا خیر مشخص کرد: IsRequired: ستون مقدار Null قبول نمی کند. IsOptional: ستون مقدار Null قبول می کند.

modelBuilder.Entity<Customer>().Property(customer => customer.FirstName).IsRequired();
modelBuilder.Entity<Customer>().Property(customer => customer.LastName).IsOptional();

 

[icon icon="fa-suitcase"]   متد IsMaxLength

این متد تعیین می کند که یک خصوصیت از نوع رشته باید خداکثر طول وارد شده را قبول کند، معادل MAX برای نوع های varchar و nvarchar در بانک اطلاعاتی:

modelBuilder.Entity<Customer>().Property(customer => customer.LastName).IsMaxLength();

 

[icon icon="fa-suitcase"]   متد HasMaxLength

بوسیله این متد می توان طول قابل قبول برای یک ستون را مشخص کرد:

modelBuilder.Entity<Customer>().Property(customer => customer.FirstName).HasMaxLength(2000);

  در صورت دادن مقدار null به ورود این متد، هیچ محدودیتی برای طول در نظر گرفته نخواهد شد.

*توجه کنید که متدهای IsMaxLength و HasMaxLength تنها برای خصوصیات از نوع رشته قابل استفاده هستند.

Attribute معادل: MaxLengthAttribute  

[icon icon="fa-suitcase"]   متد HasKey

برای تعریف یک خصوصیت به عنوان کلید، می توان از این متد استفاده کرد:

modelBuilder.Entity<Customer>().HasKey(customer => customer.CustomerID);

  Attribute معال: KeyAttribute  

[icon icon="fa-suitcase"]  متد Ignore

بوسیله این متد می توان گفت که یک خصوصیت به هیچ ستونی در بانک اشاره نمی کند:

modelBuilder.Entity<Customer>().Ignore(customer => customer.FullName);

  Attribute معادل: NotMappedAttribute  

[icon icon="fa-suitcase"]  استفاده از قابلیت Method Chaining

با استفاده از این قابلیت دیگر نیازی نیست برای هر مورد از تعریف ها برای یک خصوصیت یک خط جدا بنویسیم، به دلیل اینکه مقدار برگشتی اکثر متدها از نوع PropertyConfigurator است، می توان پس از یک دستور، دستور بعدی را نیز نوشت:

modelBuilder.Entity<Customer>().Property(customer => customer.FirstName)
    .HasColumnName("FName")
    .IsRequired()
    .HasMaxLength(2000)
    .HasColumnType("varchar");

  با این روش، در زمان صرفه جویی خواهیم کرد.

تا اینجای کار با برخی از متد ها آشنا شدیم، اما ممکن است بعضی وقت ها، Model ما خیلی بزرگ باشد، برای مثال از ۱۰۰ کلاس مختلف تشکیل شده باشد. در این جور مواقع بهتر است که یک کلاس جداگانه برای تعریف Mapping ها بنوسیم و سپس کلاس Mapping را به کلاس Context اضافه کنیم. برای این کار ابتدا یک کلاس تعریف می کنیم که از کلاس EntityTypeConfiguration مشتق شده باشد، نوع جنریک را از نوع کلاس مورد نظر انتخاب می کنیم، سپس داخل Constructor کلاس دستورات Mapping را می نویسیم:

public class CustomerMap : EntityTypeConfiguration<Customer>
{
    public CustomerMap()
    {
        HasKey(customer => customer.CustomerID);
        Property(customer => customer.FirstName)
            .HasColumnName("FName")
            .HasColumnType("varchar")
            .IsRequired()
            .HasMaxLength(2000);
        Property(customer => customer.LastName)
            .HasColumnName("LName")
            .IsOptional()
            .IsMaxLength();
    }
}

حالا این کلاس را می توانیم بوسیله دستور زیر به کلاس Context اضافه کنیم:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new CustomerMap());
}

اگر دوست داشتید به اشتراگ بگزارید