شاید برای شما هم این سوال مطرح شده باشد که Linq To Sql و Entity Framework چه تفاوتهایی دارند ، در این تایپیک این دو مورد را از جنبه های مختلفی مقایسه خواهم کرد .
1-complexity یا پیچیدگی : البته منظور از پیچیدگی از نگاه سخت و آسان بودن نیست بلکه از نگاه امکاناتی که در اختیار شما قرار می دهد . مسلما LINQ امکانات و پیچیدگیهای کمتری دارد.
2-model یا مدل سازی : ما در Entity Framework براحتی می توانیم مدل سازی کنیم علاوه بر آن از تمام ارتباطات بین جدولها پشتیبانی می کند LINQ از یک ارتباط یک به یک بین کلاسها و جدولهای بانک اطلاعاتی پشتیبانی می کند .
3-پشتیبانی از بانک اطلاعاتی : LINQ to SQL فقط از بانک اطلاعاتی Sql_Server پشتیبانی می کند در حالی که Entity Framework می تواند از بانکهای اطلاعاتی مختلفی پشتیبانی کند .
4-زمان توسعه پذیری :To SQL LINQ می تواند به راحتی استفاده شود و به سرعت کار شما را پیش ببرد . اما در نرم افزارهای پیچیده و بزرگ بدلیل داشتن امکانات محدود و کم دیگر جوابگو نیست .
5-وراثت : Entity Framework از وراثت بین کلاسها براحتی استفاده و پشتیبانی می کند در حالی که این خاصیت در LINQ وجود ندارد .
6-نوع فایل : LINQ در فایلی با پسوند DBML ذخیره می شوند در حالی که Entity Framework در فایلهای EDMX و CSDL ,SSDL که با فرمت xml است ذخیره می شوند .
7-نوع مرکب : ما در Entity Framework می توانیم فیلدی مرکب complex type تعریف کنیم . این فیلد چیزی شبیه به ساختار ها است . اما این امکان درTo SQL LINQ وجود ندارد
8-کویری : همانطور که در آموزشهای خودم نوشتم . Entity Framework از چندین سبک برای اجرای کویری استفاده می کند . Linq to Entity , EntitySQL , Query With Method
9-کارایی : هر دو از نظر سرعت در اولین اجرا شاید بتوان گفت کند هستند . اما Eitity Framework از نظر کارایی بهتر عمل می کند .
10-توسعه آینده : مایکروسافت چندان علاقه ای به توسعه و ادامه راه LINQ to SQL ندارد اما در عوض بیشتر تمرکز و توسعه را بر مبنای تکنولوژیهای دیگری گذاشته است از جمله Entity Framework
11-ساخت بانک اطلاعاتی از مدل : ما فقط در Entity Framework می توانیم ابتدا مدل خودمان را طراحی کنیم و سپس با استفاده از آن مدل ، بانک اطلاعاتی را تولید کنیم.
اگر تا به حال با برنامه نویسی سه لایه سرو کار داشتید و با آن برنامه نوشته اید حتما می دانید که این معماری از سه لایه
1- Data access layer
2- Business layer
3- Presentation layer
تشکیل شده است سوالی که مطرح می شود این است که جایگاه EDM در این معماری کدام لایه است شکل زیر تصویری بسیار گویا است که این جایگاه را به خوبی در لایه data نشان می دهد.
کار با unit test
در بخشهای قبلی در مورد دلایل تست صحبت کردم و گفتم که ما برای کار نیاز به ابزار تست داریم . یکی از این ابزارهای unit test است که شما می توانید از آدرس زیر آن را دانلود و نصب کنید . http://www.nunit.org/
پس از دانلود و نصب نرم افزار ، اکنون وقت آن است که با یک پروژه عملی نحوه کار را آموزش دهیم ، برای اینکار یک کلاس می خواهیم بسازیم که این کلاس دارای یک متد است که به دنبال یک فایل با پسوند slf می گردد . در واقع نام این فایل و پسوند به این متد ارسال می شود و در صورتی که چنین فایلی با این پسوند موجود نباشد پیغام خطا صادر می شود و در غیر اینصورت اگر پسوندی غیر از Slf باشد پیغام نادرست بودن می دهد . سورس کلاس برنامه ما بصورت زیر است . شما ابتدا یک پروژه از نوع کلاس ایجاد کنید و سپس کدهای زیر را برای تولید کلاس بنویسید :
using System;
using System.IO;
namespace LogAn
{
public class LogAnalyzer
{
public bool IsValidLogFileName(string fileName)
{
if (!File.Exists(fileName))
{
throw new Exception("No log file with that name exists");
}
if(!fileName.ToLower().EndsWith(".slf"))
{
return false;
}
return true;
}
}
}
کد بالا در واقع کد کلاس ما هستند اکنون ما می خواهیم برای کلاس بالا یک unit test بنویسیم می خواهیم عملکرد کد بالا را تست کنیم .
ابتدا باید یک سری قوانین را برای نوشتن تست بصورت قراردادی تعریف کنیم این قوانین برای خوانایی بهتر کدهای برنامه تست بسیار مفید هستند .ما در واقع برای کد بالا یک کلاس دیگری در یک پروژه جدید خواهیم نوشت که این کلاس جدید بهتر است تابع قانون زیر باشد .
نام پروژه : در پروژه بالا نام پروژه کلاس ما LogAn بود . حال برای پروژه تست چه نامی انتخاب کنیم . فرمول آن بصورت زیر است . Tests. نام پروژه این روش نام گذاری بهتر است مثلا برای پروژه کلاس بالا ، پروژه تست با نام تحت عنوان LogAn.Tests خواهد بود .
نام کلاس : در پروژه بالا نام کلاس ما LogAnalyzer است .اکنون که می خواهیم برای آن کلاس تست بنویسیم بهتر است که کلاس تست را بر اساس فرمول s Testنام کلاس بنویسیم مانند : LogAnalyzerTests
نام متد : ما یکسری متدها برای تست داریم اینجا باید مشخص و خوانا باشد که این متد قرار است کدام متد کلاس اصلی را تست کند برای اینکار از فرمول حالت رفتاری_نوع حالت تحت تست_نام متد استفاده شود البته این عبارت حاصل ترجمه عبارت انگلیسی زیر است . [MethodName]_[StateUnderTest]_[ExpectedBehavior]
حالا با توجه به توضیح قوانین بالا یک پروژه جدید با نام LogAnTests ایجاد می کنیم برای تست پروژه کلاس بالا ابتدا باید دو فایل مرجع یا refrence را به پروژه اضافه کنیم قسمت Add Refrence پروژه را انتخاب کنید و فایل dll پروژه بالا را اضافه کنید همچنین از محل نصب نرم افزار unit test باید nunit.framework را به پروژه خود اضافه کنید . اکنون بر اساس قوانین ذکر شده در بالا کلاس تست را به صورت زیر می نویسیم .
using System;
using NUnit.Framework;
namespace LogAn.Tests
{
[TestFixture]
public class LogAnalyzerTests
{
private LogAnalyzer m_analyzer=null;
[SetUp]
public void Setup()
{
m_analyzer = new LogAnalyzer();
}
[Test]
[Ignore("This test is broken")]
public void IsValidFileName_validFileLowerCased_ReturnsTrue()
{
bool result = m_analyzer.IsValidLogFileName("whatever.slf");
Assert.IsTrue(result, "filename should be valid!");
}
[Test]
public void IsValidFileName_validFileUpperCased_ReturnsTrue()
{
bool result = m_analyzer.IsValidLogFileName("WHATEVER.SLF");
Assert.IsTrue(result, "filename should be valid!");
}
[Test]
[ExpectedException(typeof(Exception),"No log file with that name exists")]
public void IsValidFileName_nunintvalidFileUpperCased_ReturnsTrue()
{
bool result = m_analyzer.IsValidLogFileName("whatever.SLF");
Assert.IsTrue(result, "filename should be valid!");
}
[TearDown]
public void TearDown()
{
m_analyzer = null;
}
}
}
فراموش نکنید که سطح دسترسی کلاس ما باید عمومی public باشد تا در حین آنالیز قابل دسترسی باشد .اکنون باید ویژگیهایی که به کلاس بالا اضافه کنیم این ویژگیها حکم تفسیر برای تست دارند که حتما باید در تست نوشته شوند .
اگر به ابتدای تست دقت کنید اول از همه ویژگی TestFixture را می بینید این ویژگی به نرم افزار nunit اعلام می کند که این کلاس تحت عمل تست است .
SetUp : ممکن است ما بخواهیم تستی را برای چند مرتبه تکرار کنیم . ما در هر بار اجرای تست باید ابتدا نمونه ای از کلاس را ایجاد کنیم و پس از اتمام تست آن نمونه از بین برود یا پاک شود . همچنین برای ایجاد یک نمونه خالی و جدید از کلاس تحت تست ما از این قسمت استفاده می کنیم . که در هر بار اجرای تست یک نمونه جدید از کلاس می سازد .تا با نمونه های قبلی تداخل ایجاد نکند .
TearDown : در واقع مکمل و پایان دهنده setup است چرا که پس از پایان تست آن نمونه از کلاس که تحت تست است باسد از پاک شود و از بین برود که دراین قسمت ما بصورت واضح می توانیم نحوه از بین بردن نمونه کلاس را اعلام کنیم.
درواقع یک تست از setup آغاز می شود و پس از اجرای فرآیندهای مختلف و متدهای مختلف با TearDown پایان می یابد مانند شکل زیر :
Test : در واقع بدنه متدهای تست را نشان می دهد .
Ignore : در برخی مواقع تست ما با شکست مواجه می شود ما باید حالتی برای عدم توقف و شکست داشته باشیم که این حالت بهترین حالت است .
اکنون پروژه خود را کامپایل کنید تا فایل dll آن ایجاد شود . خوب حالا برنامه nunit را اجرا کنید و از منوی File آن یک پروژه جدید را آغاز نموده و آنرا ذخیره کنید.سپس دوباره از همان منو و از قسمت open project فایل dll پروژه را باز کنید . فایلهای پروژه باز می شوند دکمه اجرای تست را بزنید تا تست شما اجرا شود .اگر سبز رنگ بود یعنی تست با موفقیت انجام شد اما جاهایی که قرمز رنگ است یعنی تست شما دارای اشکال است که باید برای آن حالت تغییری در کد ایجاد کنید
مقوله nunit بسیار مفصل است لذا تا همینجا اکتفا می کنم اما توجه شما را به این نکته جلب می کنم که برادر گرامی وحید نصیری در وبلاگ خود وطالب مفصلی را در این زمینه منتشر کرده اند که می توانید از لینک زیر مطالعه کنید .