مقاله کامل در مورد Shadow Properties در EF Core
مقاله کامل درباره Shadow Properties در Entity Framework
مقدمه
در Entity Framework (EF)، به طور پیشفرض هر ویژگی (Property) که در یک Entity تعریف میکنید، به عنوان یک ستون در دیتابیس ایجاد میشود. با این حال، در برخی موارد، ممکن است نیاز به ذخیره دادههایی در دیتابیس داشته باشید که هیچ ویژگی مشخصی در Entity خود نداشته باشند. برای این منظور، EF به شما اجازه میدهد که از Shadow Properties استفاده کنید. Shadow Properties ویژگیهایی هستند که در مدلهای Entity تعریف نمیشوند، اما همچنان میتوانند در دیتابیس ذخیره شوند.
در این مقاله، به توضیح مفاهیم Shadow Properties در Entity Framework پرداخته و یک مثال عملی با دو Entity به نامهای Goods و GoodsGroup ارائه خواهیم داد.

بخش اول: مفهوم Shadow Properties
Shadow Properties ویژگیهایی هستند که به طور مستقیم در کد مدل Entity شما تعریف نمیشوند، اما در دیتابیس ذخیره میشوند. این ویژگیها میتوانند در مواردی استفاده شوند که بخواهید دادههایی را در دیتابیس ذخیره کنید که نیازی به دسترسی مستقیم به آنها از طریق کد برنامه ندارید.
EF به طور خودکار برای این ویژگیها در دیتابیس یک ستون ایجاد میکند، اما این ستونها در مدلهای C# شما قابل مشاهده نیستند. این ویژگیها معمولاً برای ذخیرهسازی دادههایی که برای نظارت، زمانبندی، یا دیگر کاربردهای موقت استفاده میشوند، مفید هستند.
ویژگیهای Shadow Properties
-
عدم نیاز به تعریف در کد: Shadow Properties نیازی به تعریف در کلاس Entity ندارند.
-
ذخیرهسازی در دیتابیس: این ویژگیها میتوانند به عنوان ستونهایی در دیتابیس ذخیره شوند.
-
دسترسی از طریق API EF: شما میتوانید به این ویژگیها از طریق API Entity Framework دسترسی پیدا کنید.
بخش دوم: استفاده از Shadow Properties
در EF، برای ایجاد یک Shadow Property شما باید آن را در OnModelCreating و از طریق Fluent API تعریف کنید.
مثال عملی: تعریف Shadow Properties در Entity Framework
فرض کنید دو Entity داریم:
در این مثال، فرض کنید میخواهیم اطلاعاتی مانند تاریخ ایجاد (CreationDate) و تاریخ بهروزرسانی (LastModifiedDate) را برای هر دو Entity ذخیره کنیم. این اطلاعات ممکن است برای نظارت و مدیریت رکوردها مفید باشند، اما نیازی به تعریف مستقیم این ویژگیها در مدلها نداریم.
مرحله 1: تعریف کلاسها
ابتدا دو Entity Goods و GoodsGroup را تعریف میکنیم:
در اینجا، Goods دارای یک ارتباط به GoodsGroup است که نشاندهنده گروه کالا است.
مرحله 2: استفاده از Shadow Properties
در مرحله بعد، ما ویژگیهای CreationDate و LastModifiedDate را به صورت Shadow Property تعریف میکنیم. این ویژگیها در مدلهای Entity ما وجود ندارند، اما میخواهیم آنها را در دیتابیس ذخیره کنیم.
در این مثال، CreationDate و LastModifiedDate به عنوان Shadow Properties برای Entity های Goods و GoodsGroup تعریف شدهاند.
مرحله 3: دسترسی به Shadow Properties
برای دسترسی به Shadow Properties باید از API مربوط به EF استفاده کنیم. برای مثال، برای دسترسی به CreationDate در Entity Goods، میتوانیم به شکل زیر عمل کنیم:
در اینجا از متد Entry برای دسترسی به اطلاعات Entity و سپس از Property برای دریافت مقدار Shadow Property استفاده کردهایم.
بخش سوم: کاربردهای Shadow Properties
-
تاریخها و اطلاعات متا: معمولاً از Shadow Properties برای ذخیره تاریخهای ایجاد و بهروزرسانی، وضعیت رکوردها (مثل "حذف شده" یا "فعال")، یا اطلاعات متا استفاده میشود.
-
ایجاد رکوردهای سیستمی: اگر نیاز به ذخیره دادههایی دارید که به صورت خودکار در سطح سیستم مدیریت میشوند (مثل اطلاعات تاریخی)، میتوانید از این ویژگیها بهرهبرداری کنید.
-
فراهم کردن انعطافپذیری: برای پروژههایی که ویژگیهای خاصی باید به صورت پویا اضافه شوند، Shadow Properties به شما انعطافپذیری میدهند بدون اینکه نیاز به تغییرات زیاد در مدلهای Entity داشته باشید.
جمعبندی
Shadow Properties در Entity Framework ابزار بسیار مفیدی هستند که به شما این امکان را میدهند که دادههای اضافی را در دیتابیس ذخیره کنید بدون اینکه بخواهید آنها را به صورت صریح در مدلهای Entity خود تعریف کنید. این ویژگی به خصوص در مواردی که نیاز به ذخیرهسازی اطلاعات متا یا تاریخهای خودکار دارید، بسیار کاربردی است. با استفاده از این تکنیک، میتوانید کارایی و انعطافپذیری بیشتری در پروژههای خود داشته باشید.
ایجاد و استفاده از Shadow Properties
در این بخش، نحوه تعریف و استفاده از Shadow Property را در Entity Framework بررسی خواهیم کرد. برای مثال، فرض کنید دو Entity به نامهای Goods و GoodsGroup داریم. در این مثال، ما میخواهیم ویژگیهایی مانند GroupId را به صورت Shadow Property ایجاد کنیم، که در ارتباط بین این دو Entity به صورت خودکار توسط EF مدیریت خواهد شد.
مرحله 1: تعریف کلاسهای Goods و GoodsGroup
ابتدا دو کلاس Entity به نامهای Goods و GoodsGroup را تعریف میکنیم. در اینجا، فرض میکنیم که GroupId در کلاس Goods به طور مستقیم تعریف نشده است، اما EF به طور خودکار آن را ایجاد خواهد کرد.
در اینجا، ما هیچ ویژگی GroupId در کلاس Goods نداریم، اما انتظار داریم که EF این ویژگی را به طور خودکار برای ایجاد ارتباط بین Goods و GoodsGroup ایجاد کند.
مرحله 2: استفاده از Fluent API برای ایجاد ارتباط و Shadow Property
در مرحله بعد، برای ایجاد ارتباط بین Goods و GoodsGroup و همچنین ایجاد Shadow Property برای GroupId از Fluent API استفاده میکنیم.
در اینجا، ما از Fluent API برای ایجاد ارتباط یک به بسیاری (One-to-Many) بین Goods و GoodsGroup استفاده کردهایم. همچنین، GroupId به صورت Shadow Property تعریف شده است.

مرحله 3: دسترسی به Shadow Property
حالا که GroupId به عنوان Shadow Property ایجاد شده است، میتوانیم به این ویژگی از طریق EF دسترسی پیدا کنیم. برای دسترسی به Shadow Property، باید از متد Entry و Property استفاده کنیم:
در اینجا، با استفاده از Entry و Property میتوانیم به Shadow Property GroupId دسترسی پیدا کنیم.
بخش سوم: نحوه اعمال داده به Shadow Property
در این بخش، نحوه اعمال داده به Shadow Property به ویژه برای GroupId که در ارتباط بین Goods و GoodsGroup استفاده میشود، بررسی میکنیم.
فرض کنید میخواهید یک شیء از Goods ایجاد کنید و به طور مستقیم دادهای را به GroupId که در حالت Shadow ایجاد شده است، اعمال کنید.
برای اعمال داده به Shadow Property، میتوانیم از متد Property استفاده کنیم و مقدار مورد نظر را به آن اختصاص دهیم:
در اینجا، مقدار GroupId به طور مستقیم به Shadow Property اختصاص داده شده است و سپس شیء Goods به دیتابیس ذخیره میشود.
بخش چهارم: مزایای استفاده از Shadow Properties
استفاده از Shadow Properties در Entity Framework میتواند مزایای زیادی داشته باشد، از جمله:
-
افزایش انعطافپذیری: شما میتوانید ویژگیهایی را بدون نیاز به تغییر مدلهای Entity خود ذخیره کنید.
-
مدیریت بهینه ارتباطات: EF به طور خودکار ارتباطات را مدیریت کرده و Shadow Propertyها را ایجاد میکند، بدون اینکه نیازی به اضافه کردن ویژگیهای اضافی در کلاسها باشد.
-
پشتیبانی از ویژگیهای سیستم: شما میتوانید ویژگیهای سیستم مانند تاریخهای ایجاد و بهروزرسانی را به صورت Shadow Property اضافه کنید.
Shadow Properties در Entity Framework یک ویژگی مفید است که به شما این امکان را میدهد که دادهها را در دیتابیس ذخیره کنید بدون اینکه آنها را به طور مستقیم در مدلهای Entity خود تعریف کنید. این ویژگی به خصوص در مواردی که نیاز به ذخیرهسازی اطلاعات متا یا تاریخهای خودکار دارید، بسیار کاربردی است. با استفاده از Fluent API میتوان ارتباطات را ایجاد کرده و Shadow Propertyها را به راحتی مدیریت کرد. این قابلیت به شما این امکان را میدهد که انعطافپذیری بیشتری در طراحی مدلهای دیتابیس خود داشته باشید و از EF به شکل بهینهتری استفاده کنید.

مراحل استفاده از Migration برای Shadow Property
1. تعریف Shadow Property در مدلها
همانطور که در بخشهای قبلی توضیح دادیم، ابتدا باید Shadow Property را در مدلها تعریف کنید. فرض کنید که ما دو Entity به نامهای Goods و GoodsGroup داریم و از GroupId به عنوان Shadow Property برای ارتباط بین این دو استفاده میکنیم.
سپس، در متد OnModelCreating
از Fluent API استفاده میکنیم تا ارتباط بین Goods و GoodsGroup و همچنین Shadow Property برای GroupId را تعریف کنیم:
2. اجرای دستور Migration
پس از اینکه تغییرات مورد نظر را در مدلها ایجاد کردید، مرحله بعدی ایجاد Migration برای اعمال این تغییرات به دیتابیس است.
در ترمینال یا کنسول Package Manager دستور زیر را برای ایجاد Migration وارد کنید:
یا در کنسول Package Manager دستور زیر را وارد کنید:
این دستور باعث میشود که EF یک Migration جدید به نام AddGroupIdShadowProperty
ایجاد کند. در این مرحله، EF به صورت خودکار فیلد GroupId را به عنوان Shadow Property شبیه به سایر ویژگیها شبیهسازی خواهد کرد و آن را در فایل Migration به شکل زیر نمایش میدهد.
3. مشاهده محتوای Migration
در پوشه Migrations، یک فایل به نام AddGroupIdShadowProperty
ایجاد خواهد شد که به طور مشابه به سایر Migrations، شامل کدهایی است که تغییرات دیتابیس را نشان میدهند.
این فایل ممکن است چیزی شبیه به این باشد:
در اینجا، EF به طور خودکار ستون GroupId را در جدول Goods ایجاد میکند و این ستون را به عنوان یک کلید خارجی به جدول GoodsGroups متصل میکند.
4. اعمال Migration به دیتابیس
پس از ایجاد Migration، میتوانید آن را به دیتابیس اعمال کنید تا تغییرات در دیتابیس ذخیره شوند. برای این کار، دستور زیر را وارد کنید:
یا در کنسول Package Manager دستور زیر را وارد کنید:
این دستور باعث میشود که Migration جدید اجرا شده و ستون GroupId به دیتابیس اضافه شود.
5. مشاهده تغییرات در دیتابیس
پس از اجرای Migration و بهروزرسانی دیتابیس، اگر به دیتابیس نگاه کنید، خواهید دید که یک ستون جدید به نام GroupId به جدول Goods اضافه شده است. این ستون به عنوان یک Shadow Property در نظر گرفته شده و از طریق Fluent API برای ایجاد ارتباط با GoodsGroup استفاده میشود. در این مقاله، نحوه استفاده از Shadow Properties در Entity Framework و چگونگی ایجاد Migration برای افزودن این ویژگیها به دیتابیس را بررسی کردیم. استفاده از Shadow Properties به شما این امکان را میدهد که بدون نیاز به تعریف ویژگیهای اضافی در مدلهای خود، دادههایی را در دیتابیس ذخیره کنید. با استفاده از Fluent API میتوانید ارتباطات و ویژگیهای اضافی را به مدلهای خود اضافه کنید، و سپس با استفاده از Migration تغییرات را به دیتابیس اعمال کنید.
تاثیر Shadow Properties بر UI
در EF Core، Shadow Properties خود به خود باعث کاهش سرعت UI نمیشوند، زیرا این ویژگیها تنها در سطح پایگاه داده و مدلهای EF Core وجود دارند و در کد C# و UI هیچگونه تأثیر مستقیمی ندارند.
توضیح بیشتر:
-
عملکرد UI تحت تأثیر فرآیندهای دریافت دادهها و رندرینگ در UI است. اگر دادهها به سرعت از پایگاه داده بارگذاری شوند، UI سریعتر و روانتر خواهد بود. از آنجا که Shadow Properties در پایگاه داده ذخیره میشوند و به طور مستقیم در کد یا UI تاثیر ندارند، در صورتی که در کوئریها استفاده شوند، هیچ تأثیری بر رندر UI ندارند.
-
فرآیندهای کوئری و دادهها: تأثیر واقعی Shadow Properties بر سرعت پایگاه داده است، نه سرعت UI. اگر این ویژگیها در کوئریها استفاده شوند و پایگاه داده را تحت فشار قرار دهند (مثل ایجاد کوئریهای پیچیده یا استفاده از فیلترهای سنگین)، ممکن است سرعت واکنشهای پایگاه داده کاهش یابد، که در نهایت زمان بارگذاری دادهها برای UI را تحت تأثیر قرار میدهد.
Shadow Properties به خودی خود تأثیری بر سرعت UI ندارند، اما اگر در کوئریها به صورت نادرست یا بهطور پیچیده استفاده شوند، میتوانند زمان بارگذاری دادهها را افزایش دهند و این امر میتواند به طور غیرمستقیم باعث کاهش سرعت UI شود، بهویژه اگر دادههای زیادی از پایگاه داده بارگذاری شوند. پس، در صورت استفاده بهینه از Shadow Properties و کوئریهای بهینه، تأثیری بر UI نخواهید داشت.