PDA

View Full Version : سوال: تفاوت تبدیل ضمنی و صریح داده ها در SqlParameter



csharpcollegian
یک شنبه 16 خرداد 1395, 15:14 عصر
سلام وقت همگی به خیر
فرض کنید پروسیجر زیر رو داریم :

CREATE PROCEDURE procName
@ID int,
@Name nvarchar(50),
@Image varbinary(max),
@Admin bit
AS
BEGIN
.
.
.
END
GO
حالا با هر دو روش زیر میشه داده ها رو به این پروسیجر پاس داد.
روش اول :

.
.
.
SqlParameter idParam = new SqlParameter("@ID", id);
SqlParameter nameParam = new SqlParameter("@Name", name);
SqlParameter identificationCardParam = new SqlParameter("@Image", image);
SqlParameter adminParam = new SqlParameter("@Admin", admin);
.
.
.
روش دوم :

.
.
.
SqlParameter idParam = new SqlParameter("@ID", SqlDbType.Int);
idParam.Value = id;
SqlParameter nameParam = new SqlParameter("@Name", SqlDbType.NVarChar);
nameParam.Value = name;
SqlParameter imageParam = new SqlParameter("@Image", SqlDbType.VarBinary);
imageParam.Value = image;
SqlParameter adminParam = new SqlParameter("@Admin", SqlDbType.Bit);
adminParam.Value = admin;
.
.
.
من حدس میزنم که در روش اول تبدیل داده ها به روش ضمنی صورت میگیره و در روش دوم به صورت صریح. حالا من میخوام بدونم تفاوت این دو روش در چیه ؟
مزیت های روش دوم نسبت به روش اول چیه ؟
آیا روش اول در هیچ حالتی به مشکل نمی خوره ؟ آیا حالتی وجود داره که روش اول پاسخگو نباشه ؟
اگر هیچ تفاوتی ندارن پس چرا چنین سازنده ای برای SqlParameter گذاشتن که تووش بشه نوع رو به صورت صریح مشخص کرد ؟
خیلی ممنونم

csharpcollegian
دوشنبه 17 خرداد 1395, 13:23 عصر
دوستان کسی نظری نداره ؟

ژیار رحیمی
دوشنبه 17 خرداد 1395, 19:20 عصر
سلام
دونمونه از پیاده سازی سازنده کلاس SqlParameter هست تفاوت انچنانی باهم ندارند.بعضی مواقع در حالت run time متغیری ساخته میشود که نوع آن مشخض نیست و چون فاقد DataType خاصی میباشد در ارسال این متغییر به SqlParameter از سازنده نوع دوم آن که پارامتر ورودی از نوع Object میگیرد میتوان استفاده کرد.و وقتی نوع Object ارسال میشود SqlDataType آن بر اساس نوع Object در دانت فریم ورک استنباط میشود.تفاوت هایی در DataType ذر .Net و SQL وجود دارد وقتی DataType از نوع Object باشه تصمیم گیری بر اساس نوع ان در NET. گرفته می وشود و به نوع متناظر ان در Sql تبدیل میشود
https://msdn.microsoft.com/en-us/library/h8f14f0z(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/0881fz2y(v=vs.110).aspx
http://stackoverflow.com/questions/21396148/net-sqlparameter-constructor-inconsistent
https://msdn.microsoft.com/en-us/library/cc716729(v=vs.110).aspx

csharpcollegian
دوشنبه 17 خرداد 1395, 19:42 عصر
سلام
دونمونه از پیاده سازی سازنده کلاس SqlParameter هست تفاوت انچنانی باهم ندارند.بعضی مواقع در حالت run time متغیری ساخته میشود که نوع آن مشخض نیست و چون فاقد DataType خاصی میباشد در ارسال این متغییر به SqlParameter از سازنده نوع دوم آن که پارامتر ورودی از نوع Object میگیرد میتوان استفاده کرد.و وقتی نوع Object ارسال میشود SqlDataType آن بر اساس نوع Object در دانت فریم ورک استنباط میشود.تفاوت هایی در DataType ذر .Net و SQL وجود دارد وقتی DataType از نوع Object باشه تصمیم گیری بر اساس نوع ان در NET. گرفته می وشود و به نوع متناظر ان در Sql تبدیل میشود
https://msdn.microsoft.com/en-us/library/h8f14f0z(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/0881fz2y(v=vs.110).aspx
http://stackoverflow.com/questions/21396148/net-sqlparameter-constructor-inconsistent
https://msdn.microsoft.com/en-us/library/cc716729(v=vs.110).aspx
جناب رحیمی بابت پاسختون ازتون ممنونم.

و وقتی نوع Object ارسال میشود SqlDataType آن بر اساس نوع Object در دانت فریم ورک استنباط میشود
یعنی شما میفرمایید که کامپایلر بر اساس خود مقدار Object که پاس داده میشه، نوع داده رو تشخیص میده درسته ؟
خب حالا یه سوال، وقتی کامپایلر نوع داده رو تشخیص میده و اون رو به پروسیجر پاس میده، خب اون Object باید در متغیر متناظرش در پروسیجر قرار بگیره دیگه، درسته ؟
حالا وقتی نوع متغیر در پروسیجر مشخص شده، Object پاس داده شده مجبور نمیشه با یه تبدیل ضمنی به نوع داده ای متغیر متناظرش در پروسیجر تبدیل بشه تا بتونه در اون قرار بگیره ؟ یعنی مثلا متغیر Image هر نوعی براش توسط کامپایلر مشخص شده باشه، در نهایت وقتی میخواد توو متغیر متناظرش در پروسیجر قرار بگیره، مجبور نیست به نوع varbinary تبدیل بشه تا بتونه در اون متغیر قرار بگیره ؟ در این صورت مهم نیست که ما در سازنده SqlParameter نوعی رو برای Object مشخص می کنیم یا نه، چون در هر صورت اون Object تبدیل به نوع داده ای متغیر متناظرش در پروسیجر میشه درسته ؟
خیلی ممنونم

محمد آشتیانی
دوشنبه 17 خرداد 1395, 21:39 عصر
سلام
کامپایلر ، نوع پارامتر (SqlCommand) رو از نوع پارامتر متناظرش در Stored Procedure تشخیص نمیده ، بلکه از نوع داده ای که در Object وجود داره تشخیص میده ، برای مثال اگر شما در sp پارامتری به نام TestParam از نوع bit داشته باشید و در سمت سی شارپ یک SqlParameter رو با متد AddWithValue مقدار دهی کنید و از قضا مقدار اون رو اشتباها یک String بدید، تا زمان اجرای اون sp خطایی مشاهده نمی کنید و در زمان اجرای SqlCommand خطا رو شاهد خواهید بود.
تاکید میکنم: Net. به sp شما و نوع پارامترهای اون کاری نداره و صرفا نوع پارامتری که در SqlCommand تعریف می کنید رو بر اساس مقدار Object تعیین میکنه.

نهایتا بهتره تا جای ممکن نوع پارامترها رو به صورت صریح مشخص کنید تا احیانا به خطاهای ناخواسته برنخورید.




موفق باشید.

ASKaffash
سه شنبه 18 خرداد 1395, 06:40 صبح
سلام
SQLServer عملیات Cast را در سمت خودش انجام میدهد حتی اگر وروی شما در SP یک عدد باشد ولی شما در #C یک رشته ارسال کرده باشید تا زمانیکه عملیات Cast موفقیت آمیز باشد مشکلی نیست در غیر اینصورت خطا به #C منتقل می شود (روش اول شما) ولی اگر عملیات Cast در سمت #C انجام شده باشد (روش دوم شما) در اینصورت نباید نگران خطا در سمت SQL باشید و خطا در ابتدای کار توسط #C مدیریت خواهد شد به نظرم روش دوم خیلی فنی تر است

csharpcollegian
سه شنبه 18 خرداد 1395, 16:14 عصر
سلام
کامپایلر ، نوع پارامتر (SqlCommand) رو از نوع پارامتر متناظرش در Stored Procedure تشخیص نمیده ، بلکه...


سلام
SQLServer عملیات Cast را در سمت خودش انجام میدهد حتی اگر وروی شما در SP یک عدد باشد ولی شما...

سلام
جناب آشتیانی و ASKaffash عزیز بابت توجهتون ازتون ممنونم
اما یک سوال برام پیش اومده، فرض کنید داده هایی که قراره به پروسیجر مورد نظر پاس داده بشن، خاصیت های آبجکت زیر باشن :

class PersonEntity
{
public int ID;
public string Name;
public DateTime Date;
public byte[] Image;
public bool Admin;
.
.
.
}
و ساختار پروسیجر مورد نظر هم اینطور باشه :

CREATE PROCEDURE PersonTableInsert
@ID int,
@Name nvarchar(50),
@Date smalldatetime,
@Image varbinary(max),
@Admin bit
AS
BEGIN
.
.
.
END
GO
حالا اگر ما از روش اول برای پاس دادن داده ها استفاده کنیم، اصلا ممکن هست خطای ناخواسته ای پیش بیاد ؟ اصلا ممکن هست عملیات Cast که در سمت SQL SERVER انجام میشه به مشکل بخوره ؟ اصلا ممکن هست حالت غیرمنتظره ای پیش بیاد ؟
آیا میشه گفت "فقط کافیه برنامه نویس در طراحی آبجکت متناظر با جدول در دیتابیس، نوع خاصیت ها رو درست مشخص کنه تا با نوع فیلدهای جدول در دیتابیس تطابق داشته باشن و اگر این مساله رعایت بشه دیگه هیچ خطای ناخواسته ای پیش نمیاد و نیازی نیست با استفاده از روش دوم حجم کد رو (مخصوصا در حالاتی که تعداد پارامترها خیلی زیاده) بیهوده افزایش داد" ؟ با این استدلال که اگر خطایی هم وجود داشته باشه قبل از ورود داده ها به خاصیت های آبجکت مورد نظر مشخص و کنترل میشه و اصلا کار به کلاس SqlParameter نمیکشه ؟
آیا میشه گفت "روش دوم زمانی کاربرد داره که داده ها به صورت مستقیم از لایه نمایش دریافت و پاس داده میشن" ؟ مثلا وقتی که داده رو مستقیم از تکست باکس پاس بدیم به پروسیجر. در این حالت استفاده از روش دوم معقول تره و باعث میشه کد مطمئن تری داشته باشیم ؟
خیلی ممنونم

csharpcollegian
چهارشنبه 19 خرداد 1395, 14:14 عصر
دوستان و اساتید محترم منتظر نظرات ارزشمندتون هستم...

ASKaffash
شنبه 22 خرداد 1395, 06:53 صبح
سلام
به نظر من نمی توان اطلاعات را در این حالت غلط به SQL پاس داد برای رشته 50 کارکتری خود SQL اضافه کارکتر را حذف میکند