پیکر بندی Entity Framework با کانکشن دستی

by MDP 11. July 2011 01:10

حتمی شما توی پروژه هاتون دوست داشتید که Connection String در EF داخل فایل Web.Config یا App.Config قرار ندید که امنیت نرم افزارتون بالا بره.

ایده های زیادی در رفع مشکل فوق وجود داره ، از جمله :

    1. Encrypt کردن Web.Config (+ یک نسخه وطنی)
    2. ذخیره کردن Connection String در یک دیتابیس دیگر
    3. ذخیره کردن Connection String در یک فایل متنی مخفی
    4. Embed کردن Connection String در فایل های Resource
    5. ذخیره کردن Connection String به صورت HardCode ( البته این اصطلاح Hard Code غلطه )

شما هر کدون از این روش ها رو که استفاده کنید بازم لازم دارید که به EF بفهمونید که Connection String کدومه.Code Generator بعد از Map کردن Entity ها ، سه مدل Constructor برای مدل شما می سازه:

  1. Constructor عادی و بدون پارامتر
  2. Constructor با پارامتر ConnectionString که یک String از شما دریافت میکنه.
  3. Constructor با پارامتر Connection که از نوع “EntityConnection” هست.

مورد اول که از اطلاعات Base که توسط Code Generator ساخته میشه استفاده میکنه.مورد دوم و سوم جای بحث دارن.

برای ادامه بحث باید ابتدا ساز و کار EF رو مورد بررسی قرار بدیم.EF برای Mapping از سه فایل CSDL ، SSDL و MSL استفاده میکنه.

این سه فایل اطلاعات اصلی برای برقراری ارتباط بین EF و DataBase رو بر عهده دارن که شمال اطلاعات Entity ها ، روابط و ... میشن.

EF برای پیکر بندی به این اطلاعات نیاز داره.به خاطر همین باید توی Connetion Strnig این اطلاعات وجود داشته باشه.یعنی آدرس این سه فایل داده بشه.ولی این سه فایل هنگام Build شدن به داخل یک فایل مرکزی با پسوند EDMX ترکیب میشن.راه حل آدرس دهی سادست.شما باید از کلاس “System.Data.EntityClient.EntityConnectionStringBuilder” برای ساختن Connection استفاده کنید.

روش پیاده سازی :

string connectionString = new System.Data.EntityClient.EntityConnectionStringBuilder()
{
	Metadata = "res://*",
	Provider = "System.Data.SqlClient" /* if the provider is MS SQL */,
	ProviderConnectionString= "Reqular database connection string"
}.ConnectionString;

شاید از خودتون در مورد خط سوم یعنی آدرس دهی Metadata سوال کنید.این بخش آدرس همون سه فایل مذکور هست که باید داده می شد که به این شیوه از Resource ها خونده میشه و البته به صورت خودکار اون سه فایل رو خودش استخراج میکنه.شما فقط کافیه که این آین Connection رو که به صورت String هست به Constructor های EF بدید و تمام !

Tags: ,

.Net | EF

درست اجرا نشدن یک StoreProcedure در EF

by MDP 8. July 2011 05:59

حتمی برای شما هم اتفاق افتاده که بخشی از محاسبات و یا Logic برنامه رو به پایگاه داده واگذار کنید.مثلا قراره شما تعداد 1 ملیون رکورد که شامل اعداد تصادفی غیر تکراری هست رو به دیتابیس اضافه کنید.

بدترین راه ولی در عوض ساده ترین راه استفاده از یک حلقه For یا هرچیز دیگه ای سمت Client هست.لازم نیست توضیح بدم که این کار یعنی حدود 1 ملیون بار اتصال به پایگاه داده !

راه دوم ، استفاده از StoreProcedure هاست.در این حالت شما دیگه لازم نیست که 1 ملیون بار به پایگاه داده وصل بشید.فقط کافیه که با بار اول اتصال درخواست اجرا شدن اون SP رو باپارامتر های مورد نظر بدید.

همون طوری که میدونید EF به شما اجازه میده علاوه بر Table ها( که به صورت Entity در برنامه Map می شن) SP  و UDF های خودتون هم به EF بدید و خیلی راحت از اونا استفاده کنید.

البته مورد استفاده UDF ها و SP ها و روش معرفی اونها به EF خودش داستانی داره که از بحث الان خارجه !

فرض کنید شما SP مورد نظر ( اضافه کردن 1 ملیون رکورد ) رو نوشتید و به EF معرفی کردید.

شما حتمی مثل من این کار رو انجام میدید :

 

void DoWork()
{
   TestEntities fn = new TestEntities();
   fn.InsertOneMil();
}
 

و اجرا !

برنامه بعد از مدتی متوقف میشه و بدون هیچ خروجی خاصی مبنی بر اتمام کار آماده دریافت فرمان بعدی میشه.مشکل کجاست؟

سادست، EF برای اجرای فرامین مثل Connection های دستی دارای یک Timeout هست(البته این مورد هم مشخصه که EF بر پایه ADO.Net هست، یعنی یک لایه روی Connection و Command ! ). وقتی SP شما درحال اجرا شدن هست،بر اساس قدرت سیستم شما و شرایط دیگه ای مثل : سرت شبکه ( اگه دیتابیس روی شبکه باشه ) و … زمانی رو میگیره که بیشتر از حد معمول EF هست.

برای رفع این مشکل فقط کافیه که به صورت دستی این مقدار رو عوض کنید.

برای تغییر این مقدار دو راه پیش رو دارید :

1 – تغییر تعریف پیشفرض در خود Model

2 – تغییر در مواقع لزوم.

هر روش کارایی خودش رو داره که من هر دو روش رو اینجا میگم.

برای روش اول شما باید Source مدل رو باز کنید و مقدار CommandTimeout رو دستی عو�� کنید :

1

حالا فقط کافیه که در Constructors اصلی خود Context مقدار جدید رو اعمال کنید :

 
public TestEntities() : base("name=TestEntities", "TestEntities")
     {
         this.ContextOptions.LazyLoadingEnabled = true;
         this.CommandTimeout = 999999;
         OnContextCreated();
     }
 

این روش وقتی کارایی داره که شما هرکجا که از EF توی برنامتون استفاده می کنید نیاز به Timeout بالا دارید و نمیخواید که هر دفعه این مقدار رو Set کنید.این روش پیشنهاد خوبی نیست.چون خیلی از امکانات رو از دست میدید.

روش دوم منطقی تر از روش اول هست.شما کافیه هرکجا که خواستید یعدر از ساختن یک نمونه از Context مقدار CommantTimeout رو ست کنید:

TestEntities fn = new TestEntities();
fn.CommandTimeout = 999999;

Tags: ,

.Net

My Groups

Poll

از چه پلتفرمی برای توسعه استفاده می کنید



Show Results

Month List