پیکربندی Property Mapping ها با استفاده از Fluent API در Entity Framework Code First


با استفاده از Fluent API می‌توان رفتارهای پیش‌فرض Entity Framework در نگاشت کردن property های مربوط به یک entity به ستون های مربوط به یک جدول در دیتابیس را پیکربندی کرد. به راحتی با استفاده از این روش می توان نام ستون و type و سایز و null بودن و یا NotNull بودن آن و primary key و foreign key و concurrency column ‌ها و بسیاری از موارد دیگر را پیکربندی نمود. به منظور بررسی مطالب مربوط به این مقاله از دو entity class با نام‌های Student و Standard شبیه به کد زیر استفاده خواهیم کرد.

public class Student

{

public int StudentKey { get; set; }

public string StudentName { get; set; }

public DateTime DateOfBirth { get; set; }

public byte[] Photo { get; set; }

public decimal Height { get; set; }

public float Weight { get; set; }

public Standard Standard { get; set; }


public class Standard

{

public int StandardKey { get; set; }

public string StandardName { get; set; }

public ICollection<Student> Students { get; set; }

}پیکربندی کردن primary key ها و composite primary key ‌ها

همانطور که در تعریف دو کلاس بالا مشاهده می کنید domain class هایی که در این قسمت داریم از convention های مربوط به روش code-first در Entity Framework استفاده نمی‌کنند. به عبارت دیگر آنها دارای هیچ property خاصی که بتوان بر اساس convention ها آنها را به عنوان کلید اصلی لحاظ کرد نیستند. بنابراین می‌توانیم با استفاده از یک متد به نام HasKey یک کلید را برای این domain class ‌ها لحاظ کنیم. همانطور که قبلاً نیز گفتیم در ابتدا می بایست با استفاده از متد جنریک Entity کلاس مورد نظر را انتخاب کنیم. دقت کنید که خروجی متد جنریک Entity یک object از نوع EntityTypeConfiguration می باشد. لطفاً به مثال زیر دقت کنید.

public class SchoolContext: DbContext

{

public SchoolDBContext(): base()

{

}

public DbSet<Student> Students { get; set; }

public DbSet<Standard> Standards { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

//Configure primary key

modelBuilder.Entity<Student>().HasKey<int>(s => s.StudentKey);

modelBuilder.Entity<Standard>().HasKey<int>(s => s.StandardKey);

//Configure composite primary key

modelBuilder.Entity<Student>().HasKey<int>(s => new { s.StudentKey, s.StudentName });

}

}

پیکربندی نام ستون و Data Type و Order آن با استفاده از Fluent API

بر اساس convention های پیش فرض در Entity Framework و روش code-first یک ستون هم نام با property تعریف شده، تعریف می‌شود. علاوه بر این order و data type مربوط به آن ستون در جدول نیز بر اساس convention ها لحاظ می گردد. به راحتی می‌توان با استفاده از Fluent API این پیکربندی ها را override کرد. کدی که در قسمت زیر مشاهده می کنید این موضوع را نشان می‌دهد.

public class SchoolContext: DbContext

{

public SchoolDBContext(): base()

{

}

public DbSet<Student> Students { get; set; }

public DbSet<Standard> Standards { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

//Configure Column

modelBuilder.Entity<Student>()

.Property(p => p.DateOfBirth)

.HasColumnName("DoB")

.HasColumnOrder(3)

.HasColumnType("datetime2");

}

}

همانطور که در این مثال می بینید از یک متد به نام Property برای پیکربندی کردن یک property از یک Entity استفاده نموده ایم. متد HasColumnName برای پیکربندی کردن نام ستون متناظر با یک property در جدول دیتابیس مورد استفاده قرار می‌گیرد. از این متد برای پیکربندی کردن یک property به نام DateOfBirth استفاده کرده ایم. علاوه بر این متدهای HasColumnOrder و HasColumnType به منظور پیکربندی کردن order و data type مربوط به ستون های متناظر با property مورد نظر لحاظ شده اند. علاوه بر این متد Property اجازه می دهد از روش‌های مختلفی برای پیکربندی کردن یک property استفاده کنید. تصویر زیر این موضوع را نشان می‌دهد.

پیکربندی کردن ستونهای Null و NotNull با استفاده از Fluent API

به صورت پیش‌فرض Entity Framework یک ستون از نوع NotNull را برای property هایی که primitive data type هستند ایجاد می‌کند. این موضوع به این دلیل است که primitive data type ها نمی توانند null باشند؛ مگر اینکه با استفاده از علامت ؟ و یا از نوع nullable تعریف شده باشند. به راحتی می‌توان با استفاده از متد IsOptional یک ستون nullable را برای یک property ایجاد کرد. علاوه بر این می توان با استفاده از متد IsRequired یک ستون به صورت NotNull را تعریف نمود. کدی که در قسمت زیر مشاهده می کنید این موضوع را نشان می‌دهد.

public class SchoolContext: DbContext

{

public SchoolDBContext(): base()

{

}

public DbSet<Student> Students { get; set; }

public DbSet<Standard> Standards { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

//Configure Null Column

modelBuilder.Entity<Student>()

.Property(p => p.Heigth)

.IsOptional();

//Configure NotNull Column

modelBuilder.Entity<Student>()

.Property(p => p.Weight)

.IsRequired();

}

}پیکربندی اندازه یک ستون با استفاده از Fluent API

روش code-first به صورت پیش‌فرض حداکثر اندازه را برای data type مربوط به یک ستون لحاظ می‌کند. به راحتی می‌توان این convention را override نمود. کدی که در قسمت زیر مشاهده می کنید این موضوع را نشان می‌دهد.

public class SchoolContext: DbContext

{

public SchoolDBContext(): base()

{

}

public DbSet<Student> Students { get; set; }

public DbSet<Standard> Standards { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

//Set StudentName column size to 50

modelBuilder.Entity<Student>()

.Property(p => p.StudentName)

.HasMaxLength(50);

//Set StudentName column size to 50 and change datatype to nchar

//IsFixedLength() change datatype from nvarchar to nchar

modelBuilder.Entity<Student>()

.Property(p => p.StudentName)

.HasMaxLength(50).IsFixedLength();

//Set size decimal(2,2)

modelBuilder.Entity<Student>()

.Property(p => p.Height)

.HasPrecision(2, 2);

}

}

همانطور که در این مثال می بینید ما از یک متد به نام HasMaxLength استفاده کرده‌ایم تا اندازه یک ستون را تنظیم کنیم. علاوه بر این متد IsFixedLength به راحتی nvarchar را به nchar تبدیل می کند. متد دیگری که استفاده کرده‌ایم HasPrecision نام دارد که سطح دقت یک ستون از نوع decimal را تنظیم می‌کند.

پیکربندی کردن ستون Concurrency در Fluent API

به راحتی می‌توان به یک property را به عنوان یک concurrency column با استفاده از متد ConcurrencyToken لحاظ نمود. این موضوع در کد زیر نشان داده شده است.

public class SchoolContext: DbContext

{

public SchoolDBContext(): base()

{

}

public DbSet<Student> Students { get; set; }

public DbSet<Standard> Standards { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

//Set StudentName as concurrency column

modelBuilder.Entity<Student>()

.Property(p => p.StudentName)

.IsConcurrencyToken();

}

}

همانطور که در این مثال می بینید ما از یک ستون به نام StudentName به عنوان concurrency column استفاده کرده‌ایم تا مقدار مربوط به آن در جملات where و در زمان بروز رسانی کردن و یا حذف کردن رکوردها لحاظ بشود. علاوه بر این می توان از یک متد به نام IsRowVersion استفاده کرد تا یک property که از نوع []byte است به عنوان یک concurrency column استفاده نمود.

منبع: وبسایت پرووید