PDA

View Full Version : استفاده مناسب از کلاس های SQL در ویژوال دات نت



sasan_22
پنج شنبه 14 دی 1391, 02:59 صبح
با سلام
در رابطه با ارتباط با بانک اطلاعاتی می توان از ADO.NET و همچنین از LINQ استفاده نمود . منتها از آنجایی که ADO.NET کلاس هایی زیادی برای انجام کارهای گوناگون در اختیار می گذارد گاهی کاربر (برنامه نویس) را گیج و سردر گم می کند(که دقیقا من دچار این موضوع شدم). سوال اساسی که دارم اینه که به چند روش می توان در جدول کتاب در بانکمان رکورد ذخیره نمود (یعنی عملیات Insert) فرض کنید این جدول شامل فیلد آی دی - نام کتاب و قیمت می باشد . بدین صورت :

Book - ID,Name,Price




ممنون

mousa1992
پنج شنبه 14 دی 1391, 03:41 صبح
اقا نصف شبی کسی دیگه نیست گیر من افتادی :لبخند:
تا اونجایی که میدونم برا ثبت ی رکورد راهی جز دستور insert نیست ، مگه اینکه از ویزاردها استفاده کنی و bind کردن که باهاشون کار نکردم

govaleshgar2
پنج شنبه 14 دی 1391, 04:44 صبح
ویژوال دات نت؟؟؟؟؟؟؟

راهها و روشهای زیادی برای ثبت یک رکورد وجود داره. ولی به طور کلی در Ado.Net دو سطح API وجود دارد. مدل قدیمی که مبتنی بر مجموعه گونه های xxConnection xxCommand xxDataAdapter DataSet DataTable DataRow است و مدل جدید که اساساً ORM است و Entity Framework نام دارد. یک حالت سومی هم مدتی ارائه شد(و هنوز در خیلی جاها استفاده میشود که اون هم ORM بود ولی مایکروسافت اون رو کنار گذاشت به نام Linq to Sql).

حالا مدل قدیمی رو میتونستی به دو شکل بکار ببری: Disconnected یا Connected: در Disconnected تغییرات رو در DataSet اعمال میکنید و بعد با استفاده از DataAdapter همه تغییرات را persist میکنید. در Connected مستقیماً دستورات Sql را توسط xxCommand اجرا میکنید.

در Entity Framework هر چند میتوانید مستقیماً دستورات را مستقیماً اجرا کنید اما روش پیشنهادی(اصلی) مبتنی بر نگاشت رابطه ای-شی گرا(ORM) است. حالا اینجا چندین مدل هست که میتونی Entity Framework را به کار ببری:
Code First
Model First
Database First

در Code First با تعریف کلاسهای C# (یا هر زبان دیگری) ساختار داده را تعریف میکنی، بعد بر اساس این ساختار EF ساختار دیتابیس مورد نظر را پیشنهاد میدهد و باقی ماجرا..
در Model First از طریق یک Designer مدل داده ها را تعریف میکنی بعد EF هم کلاسهای C# و هم ساختار داده را برات تعریف میکنه و باقی ماجرا ...
در Database First یک پایگاه داده موجود رو میدی و بر اساس اون هم مدل و هم کلاسهای C# توسط EF ساخته میشود و باقی ماجرا ...

حالا بپردازیم به باقی ماجرا، باقی ماجرا اینه که صرف نظر از اینکه چطور طراحی مدل و کلاسها رو شروع کردی برای کار با این ORM شما یک context باز میکنی و بعد تو اشیا تغییرات مورد نظر رو میدهی(تغییرات را در اشیایی میدهی که به context وصل(attach) باشند) و بعد وقتی که لازم بود به context میگی که تمام اشیا attach شده به خودش را تغییراتش رو ذخیره کند.

حالا گزینه هایی که در EF با آن سر و کار داری:
اینکه اشیا self tracking باشند(یعنی اینکه خودشون رد تغییرات خودشون رو نگه دارند و گزارش بدهند) یا self tracking نباشند(یعنی اینکه context باید آمار تغییرات را خودش دربیاره)
اینکه کلاسهات POCO هستند یا نه
در حالت Code First باید انتخاب کنی که از Attribute ها برای مدل سازی استفاده کنی یا از Modeling API (که فکر کنم اسمش fluent configuration باشد) - البته میتونی از هردوشون همزمان استفاده کنی و fluent configuration اولویت داره نسبت به attribute ها و در ضمن کارآمدتر هم هست.

با این حساب حداقل 8-10 راه مختلف وجود داره که بایستی از بینشون انتخاب کنی

govaleshgar2
پنج شنبه 14 دی 1391, 04:54 صبح
در ارتباط به سوالت بعد نیست این موضوع رو هم بگم که رابطه بین کلاسهای Ado.Net و دستورات Sql مانند Insert و Update و Delete و Select چیست؟

در مدل Ado.Net قدیمی یعنی زمانی که از کلاسهایی مانند xxConnection xxCommand xxDataAdapter DataSet DataTable DataRow استفاده میکنی باید این دستورات Sql را به این کلاسها بدهی تا بتوانی با پایگاه داده تعامل داشته باشی.
در مد Disconnected این دستورات را توسط DataAdapter به طور کلی تعیین میکنی (یعنی برای هر جدول چهار دستور فوق را تعیین میکنی تا هر تغییری را ذخیره کنند)
در مد Connected دستورات Sql را توسط xxCommand مستقیماً اجرا میکنی.

اما Entity Framework همانطور که گفتم یک ORM است پس شما لازم نیست که مستقیماً دستورات SQL را بنویسی و EF خودش جور این کار را میکشد و متناسب با تغییرات داده شد دستورات SQL مورد نیاز را تولید کرده و اجرا میکند.

sasan_22
پنج شنبه 14 دی 1391, 12:05 عصر
خب اینطور که متوجه شم EF کار برنامه نویس رو کم میکنه یعنی میتونم بگم هر یک دستور در EF معادل سه دستور در ADO.NET هست . چون با EF آشناییت ندارم سوالهای گوناگون برام ایجاد شده که یکی از این سوال ها ای تاپیکه: http://barnamenevis.org/showthread.php?377117-%D8%A7%D9%86%D8%AC%D8%A7%D9%85-%D9%85%D8%B1%D8%A7%D8%AD%D9%84-Update-Insert-Delete-%D8%A8%D8%B5%D9%88%D8%B1%D8%AA-Virtual
و چند سوال یگه در رابطه با ADO.NET :
1- آیا برای فرستادن یک دستور TSQL بهتره از SqlDSaatAdapter استفاده بشه یا کلاس های دیگه ( مثل DataSet)؟؟
2-(سوال مهم) آیا استفاده از دیتا ست را در برنامه پیشنهاد میکنید یا نه؟( دوستان توجه داشته باشید کمی سرعت عملیات درج و... مطرحه در واقع میتوان گفت بهترین دستوری که میتوان برای برقراری با بانک - اجرای دستورات - خاتمه ارتباط داشته باشیم چیه؟ فرض کنی رکوردی رو میخواهید پاک کنید)
3- آیا برای هر دستور TSQL که قراره اجرا بشه در برنامه مان - حتما باید کانکشن رو باز و بسته کنیم؟؟ (یعنی نمیشه یه کانکشن ساخت که در لود برنامه باز بشه و تا خاتمه برنامه - زمانی که کاربر برنامه را نبسته - کانکشن رو نبندیم؟؟ چه دلیلی داره که کانکشن باید بسته شه در حالی ممکنه چند لحظه بعد دوباره یه دستور TSQL اجرا شه؟؟)
4- آیا با باز بودن کانکشن میتوان گفت امنیت داده ها ب خطر میافته؟؟(حالا به هر نحو چه عمدا چه سهوا - عواقب نبستن کانکشن)
5-آیا میتوان انعطافی که دستورات Select داریم ( از جمله Join و ...) با LINQ پیاده سازی کرد ( خصوصا سلکت های تو در تو) ؟؟
6- جهت ایجاد تراکنش در دستورات برنامه بهتره Transact و Commit رو در برنامه بذاریم تا توی خود دستورات به صورت رشته؟
7-برای select کردن یه جدول (یعنی همراه با شرط ) به چند شیوه میتوان این کار را انجام داد ؟(یعنی چند روش وجود داره که دستور فرستاده شده رو به دیتا گریدمان bind کنیم .مثلا SqlDataReader یا ...)

sasan_22
پنج شنبه 14 دی 1391, 12:12 عصر
دوست عزیز آقای govaleshgar2
من چند بار پست 3 رو خوندم و به این نتیجه رسیدم که : دوره ADO.NET تموم شده و جای گزینی هم که برای اون گرفته بودند (LINQ TO SQL) هم توسط EF داره نقشش کمرنگ میشه درسته؟؟

govaleshgar2
پنج شنبه 14 دی 1391, 16:55 عصر
خب اینطور که متوجه شم EF کار برنامه نویس رو کم میکنه یعنی میتونم بگم هر یک دستور در EF معادل سه دستور در ADO.NET هست . چون با EF آشناییت ندارم سوالهای گوناگون برام ایجاد شده که یکی از این سوال ها ای تاپیکه: http://barnamenevis.org/showthread.php?377117-%D8%A7%D9%86%D8%AC%D8%A7%D9%85-%D9%85%D8%B1%D8%A7%D8%AD%D9%84-Update-Insert-Delete-%D8%A8%D8%B5%D9%88%D8%B1%D8%AA-Virtual
و چند سوال یگه در رابطه با ADO.NET :
1- آیا برای فرستادن یک دستور TSQL بهتره از SqlDSaatAdapter استفاده بشه یا کلاس های دیگه ( مثل DataSet)؟؟
2-(سوال مهم) آیا استفاده از دیتا ست را در برنامه پیشنهاد میکنید یا نه؟( دوستان توجه داشته باشید کمی سرعت عملیات درج و... مطرحه در واقع میتوان گفت بهترین دستوری که میتوان برای برقراری با بانک - اجرای دستورات - خاتمه ارتباط داشته باشیم چیه؟ فرض کنی رکوردی رو میخواهید پاک کنید)
3- آیا برای هر دستور TSQL که قراره اجرا بشه در برنامه مان - حتما باید کانکشن رو باز و بسته کنیم؟؟ (یعنی نمیشه یه کانکشن ساخت که در لود برنامه باز بشه و تا خاتمه برنامه - زمانی که کاربر برنامه را نبسته - کانکشن رو نبندیم؟؟ چه دلیلی داره که کانکشن باید بسته شه در حالی ممکنه چند لحظه بعد دوباره یه دستور TSQL اجرا شه؟؟)
4- آیا با باز بودن کانکشن میتوان گفت امنیت داده ها ب خطر میافته؟؟(حالا به هر نحو چه عمدا چه سهوا - عواقب نبستن کانکشن)
5-آیا میتوان انعطافی که دستورات Select داریم ( از جمله Join و ...) با LINQ پیاده سازی کرد ( خصوصا سلکت های تو در تو) ؟؟
6- جهت ایجاد تراکنش در دستورات برنامه بهتره Transact و Commit رو در برنامه بذاریم تا توی خود دستورات به صورت رشته؟
7-برای select کردن یه جدول (یعنی همراه با شرط ) به چند شیوه میتوان این کار را انجام داد ؟(یعنی چند روش وجود داره که دستور فرستاده شده رو به دیتا گریدمان bind کنیم .مثلا SqlDataReader یا ...)


1- سوالت رو نفهمیدم. منظورت از فرستادن دستور چیه؟؟
2- DataSet ابزار خیلی خوبی است که در بسیاری موارد کارایی دارد. نگرانی شما در مورد سرعت عملیات وارد نیست. بهترین هم وجود ندارد.
3- بهتره که کانکشن رو ببندی. سوال اینه که چه دلیلی داره کانکشن رو باز نگه داری؟ اگه نگران سرعت و کارایی هستی، باز هم وارد نیست.
4- ربطی نداره.
5- به طور کلی جواب مثبته. Entity Framework پوشش خوبی در این زمینه دارد و با LINQ میتوانید معادل هر شکل ممکنی از دستورات Select در Sql را به نتیجه برسانید. Join هم پشتیبانی شده است.
6- باز هم متوجه نشدم سوال چیه.
7- باز هم هزار و یک روش وجود دارد، چیزی که باید به اون بپردازی تعداد روشها نیست، بلکه این مهمه که در چه سناریویی چه روشی مناسبتره؟؟ برای چه نوع نرم اقزاری چه تکنولوژی بهتره؟
البته من خودم هرگز در سطح UI خواندن و نوشتن در دیتابیس را انجام نمیدهم و به شما هم توصیه میکنم این کار را نکنید، باید ابتدا داده ها را خواند و بعد در ساختمان داده مستقل از Data Access منتثل کرد و بعد در UI نمایش داد.

govaleshgar2
پنج شنبه 14 دی 1391, 17:31 عصر
دوست عزیز آقای govaleshgar2
من چند بار پست 3 رو خوندم و به این نتیجه رسیدم که : دوره ADO.NET تموم شده و جای گزینی هم که برای اون گرفته بودند (LINQ TO SQL) هم توسط EF داره نقشش کمرنگ میشه درسته؟؟

البته Entity Framework خودش بخشی از Ado.Net است و من گمان نمیکنم EF یک جایگزین برای ابزارهای قبلی تر باشد، بلکه صرفاً ابزاریست مکمل برای زمانی که به ORM احتیاح هست. ولی به طور کلی هر چیزی در جای خودش کاربرد خودش رو داره.

sasan_22
پنج شنبه 14 دی 1391, 19:50 عصر
دوست عزیز آقای govaleshgar2
ممنون از جوابهای خوبتون - فقط ابهامات موجو در سوالهامو بگم شاید بهتر متوجه شید:
1- برای اینکه در برنامه س شارپ یک دستور TSQL را اجرا کنیم ابزار موجو فقط SqlDataAdapter هست یا میتوان از چیزهای دیگه هم استفاده نمود ؟ (مثلا دستور رو داخل SqlCommand بنویسی و توسط متد ExecuteNonReader اجرا کنی)

6- در رابطه با تراکنش ها در دستورات TSQL هست میخوام بدونم آیا دستورات من (مثلا حذف رکورد) کاملا و صحیح انجام شده یا نه؟ خب برای این کار باید از BEGIN TRANSC استفاده کرد مثال Microsoft :


BEGIN TRAN T1
UPDATE table1 ...
BEGIN TRAN M2 WITH MARK
UPDATE table2 ...
SELECT * from table1
COMMIT TRAN M2
UPDATE table3 ...
COMMIT TRAN T1


حالا این موضوع را میتوان در محیط برنامه نویسی سی شارپ انجام داد :


private static void ExecuteSqlTransaction(string connectionString)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();

SqlCommand command = connection.CreateCommand();
SqlTransaction transaction;

// Start a local transaction.
transaction = connection.BeginTransaction("SampleTransaction");

// Must assign both transaction object and connection
// to Command object for a pending local transaction
command.Connection = connection;
command.Transaction = transaction;

try
{
command.CommandText =
"Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";
command.ExecuteNonQuery();
command.CommandText =
"Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";
command.ExecuteNonQuery();

// Attempt to commit the transaction.
transaction.Commit();
Console.WriteLine("Both records are written to database.");

catch (Exception ex)
{
Console.WriteLine("Commit Exception Type: {0", ex.GetType());
Console.WriteLine(" Message: {0", ex.Message);

// Attempt to roll back the transaction.
try
{
transaction.Rollback();

catch (Exception ex2)
{
// This catch block will handle any errors that may have occurred
// on the server that would cause the rollback to fail, such as
// a closed connection.
Console.WriteLine("Rollback Exception Type: {0", ex2.GetType());
Console.WriteLine(" Message: {0", ex2.Message);


به نظر شما کدوم روش بهتره؟؟