پیشنیاز:
تعریف نوع جنریک به صورت متغیر
مطلبی را چندی قبل در مورد نحوه خودکار کردن افزودن کلاسهای EntityTypeConfiguration به modelBuilder در این سایت مطالعه کردید. در مطلب جاری به خودکار سازی تعاریف مرتبط با DbSetها خواهیم پرداخت.
ابتدا مثال کامل زیر را درنظر بگیرید:
توضیحات:
همانطور که ملاحظه میکنید در این مثال خبری از تعاریف DbSetها نیست. به کمک Reflection تمام مدلهای برنامه که از نوع کلاس پایه BaseEntity هستند (روشی مرسوم جهت مدیریت خواص تکراری مدلها) یافت شده (در متد loadEntities) و سپس نتیجه حاصل به صورت پویا به متد جنریک Entity ارسال میشود. حاصل، افزوده شدن خودکار کلاسهای مورد نظر به سیستم EF است.
البته در این حالت چون دیگر کلاسهای مدلها در MyContext به صورت صریح تعریف نمیشوند، نحوه استفاده از آنها را توسط متد Set، در متدهای RunTests و یا Seed، ملاحظه میکنید.
تعریف نوع جنریک به صورت متغیر
مطلبی را چندی قبل در مورد نحوه خودکار کردن افزودن کلاسهای EntityTypeConfiguration به modelBuilder در این سایت مطالعه کردید. در مطلب جاری به خودکار سازی تعاریف مرتبط با DbSetها خواهیم پرداخت.
ابتدا مثال کامل زیر را درنظر بگیرید:
using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; using System.Reflection; namespace MyNamespace { public abstract class BaseEntity { public int Id { set; get; } public string CreatedBy { set; get; } } public class User : BaseEntity { public string Name { get; set; } } public class MyContext : DbContext { protected override void OnModelCreating(DbModelBuilder modelBuilder) { var asm = Assembly.GetExecutingAssembly(); loadEntities(asm, modelBuilder, "MyNamespace"); } void loadEntities(Assembly asm, DbModelBuilder modelBuilder, string nameSpace) { var entityTypes = asm.GetTypes() .Where(type => type.BaseType != null && type.Namespace == nameSpace && type.BaseType.IsAbstract && type.BaseType == typeof(BaseEntity)) .ToList(); var entityMethod = typeof(DbModelBuilder).GetMethod("Entity"); entityTypes.ForEach(type => { entityMethod.MakeGenericMethod(type).Invoke(modelBuilder, new object[] { }); }); } } public class Configuration : DbMigrationsConfiguration<MyContext> { public Configuration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } protected override void Seed(MyContext context) { context.Set<User>().Add(new User { Name = "name-1" }); context.Set<User>().Add(new User { Name = "name-2" }); context.Set<User>().Add(new User { Name = "name-3" }); base.Seed(context); } } public static class Test { public static void RunTests() { Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>()); using (var context = new MyContext()) { var user1 = context.Set<User>().Find(1); if (user1 != null) Console.WriteLine(user1.Name); } } } }
همانطور که ملاحظه میکنید در این مثال خبری از تعاریف DbSetها نیست. به کمک Reflection تمام مدلهای برنامه که از نوع کلاس پایه BaseEntity هستند (روشی مرسوم جهت مدیریت خواص تکراری مدلها) یافت شده (در متد loadEntities) و سپس نتیجه حاصل به صورت پویا به متد جنریک Entity ارسال میشود. حاصل، افزوده شدن خودکار کلاسهای مورد نظر به سیستم EF است.
البته در این حالت چون دیگر کلاسهای مدلها در MyContext به صورت صریح تعریف نمیشوند، نحوه استفاده از آنها را توسط متد Set، در متدهای RunTests و یا Seed، ملاحظه میکنید.