PDA

View Full Version : آموزش: اموزش نحوه استفاده از پارامتر ها



mohsen.nsb44
سه شنبه 08 تیر 1389, 09:52 صبح
سلام خدمت دوستان محترم همان طور كه در تاپيك هاي قبل مشاهده كرديد من براي ثبت يك ركورد با استفاده از پارامتر ها دچار مشكل مي شدم حال تونستم اين مشكلو حل كنم تصميم گرفتم كد صحيح رو بزارم تا اگه كسي مثل من چنين مشكلي داشت بتونه حل كنه
از دوستان حرفه اي و اساتيد خواهشمندم اگه اين كد از نظر امنيتي مشكل داره عنوان كنند تا ما حلش كنيم


sqlconnection con;
sqldataadaptor da;
dataset ds=new dataset();
string s1,s2;



روي دكمه ثبت كليك كرده و در قسمت كد، كد زير رو بنويسيد


s1=@"data source=.\sqlexpress;initial catalog=dbName;integrated security=true";
con=new sqlconnection(s1);
con.open();
s2="insert into TableName(name)values('"+textbox1.text+"')";
da=new sqldataadaptor(s2,con);
da.fill(ds,"tableName);
con.close

raziee
سه شنبه 08 تیر 1389, 11:16 صبح
اگه اين كد از نظر امنيتي مشكل داره عنوان كنند تا ما حلش كنيم
s2="insert into TableName(name)values('"+textbox1.text+"')";

این روش احتمال تظریق کد های SQL رو بالا میبره.

mohsen.nsb44
سه شنبه 08 تیر 1389, 11:21 صبح
این روش احتمال تظریق کد های SQL رو بالا میبره.
خب الان با اين كد ديگه با دستور مستقيم اس كيو ال اطلاعات ثبت نمي شه
يكي از دوستان اشاره كرده بودند كه اگر اطلاعات با دستور مستقيم اسكيو ال ثبت بشه مشكل افرين ميشه مثل كد زير

sqldatasource1.insertcomman="insert into tablename(name)values('"+textbox1.text+"')";

خب تو كد هاي بالا مشكل از كجاست من به صورت مستقيم اطلاعات رو ثبت نكردم چطور بايد مشكلش رفع بشه؟؟؟؟

raziee
سه شنبه 08 تیر 1389, 11:33 صبح
تا اونجایی که بنده اطلاع دارم. بهترین روش ارسال به بانک کدی شبیه به کد زیر هست.
public override bool Insert(EntityContent content)
{
SqlConnection cnn = new SqlConnection(this.ConnectionString);
SqlCommand cmd = new SqlCommand("sp_Content_Insert", cnn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@ContentName", SqlDbType.NVarChar, 50).Value = content.ContentName;
cmd.Parameters.Add("@Content", SqlDbType.NText).Value = content.Content;
cmd.Parameters.Add("@LastEditDate", SqlDbType.DateTime).Value = content.LastEditDate;

try
{
cnn.Open();
int isInserted = this.ExecuteNonQuery(cmd);
return (isInserted == 1);
}
catch (SqlException)
{
throw;
}
catch (Exception)
{
throw;
}
finally
{
if (cnn.State != ConnectionState.Closed)
{
cnn.Close();
cmd.Dispose();
}
}
}

mohsen.nsb44
سه شنبه 08 تیر 1389, 11:36 صبح
تا اونجایی که بنده اطلاع دارم. بهترین روش ارسال به بانک کدی شبیه به کد زیر هست.
public override bool Insert(EntityContent content)
{
SqlConnection cnn = new SqlConnection(this.ConnectionString);
SqlCommand cmd = new SqlCommand("sp_Content_Insert", cnn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@ContentName", SqlDbType.NVarChar, 50).Value = content.ContentName;
cmd.Parameters.Add("@Content", SqlDbType.NText).Value = content.Content;
cmd.Parameters.Add("@LastEditDate", SqlDbType.DateTime).Value = content.LastEditDate;

try
{
cnn.Open();
int isInserted = this.ExecuteNonQuery(cmd);
return (isInserted == 1);
}
catch (SqlException)
{
throw;
}
catch (Exception)
{
throw;
}
finally
{
if (cnn.State != ConnectionState.Closed)
{
cnn.Close();
cmd.Dispose();
}
}
}
ميشه در مورد كد هاتون يكم توضيح بدين؟مشكل كد من چي بود چطور ميشه رفعش كرد؟

raziee
سه شنبه 08 تیر 1389, 11:47 صبح
ميشه در مورد كد هاتون يكم توضيح بدين؟مشكل كد من چي بود چطور ميشه رفعش كرد؟
کدوم قسمتش رو نفهمیدید، همون رو توضیح بدم.
البته این کد از یک کلاس زیر مجموعه شده.
protected int ExecuteNonQuery(DbCommand command)
{
return command.ExecuteNonQuery();
}
-------------
ببینید شما با DataSet و DataAdaptor کار میکنید.
خود این ها باعث کاهش سرعت میشن.
قبلا جناب راد یک رفرنسی رو داده بودند که توضیحاتی رو داده بود که دلایل کاهش سرعت به خاطره چیه.

mohsen.nsb44
سه شنبه 08 تیر 1389, 11:52 صبح
کدوم قسمتش رو نفهمیدید، همون رو توضیح بدم.
البته این کد از یک کلاس زیر مجموعه شده.
protected int ExecuteNonQuery(DbCommand command)
{
return command.ExecuteNonQuery();
}
-------------
ببینید شما با DataSet و DataAdaptor کار میکنید.
خود این ها باعث کاهش سرعت میشن.
قبلا جناب راد یک رفرنسی رو داده بودند که توضیحاتی رو داده بود که دلایل کاهش سرعت به خاطره چیه.
سايت من حجمش خيلي كمه چه از نظر كد نويسي چه از نظر تصاوير استفاده شده و ...
من مشكل زيادي داشتم واسه ثبت يك ركورد با استفاده از پارامتر ها الان تونستم بوسيله كد بالا مشكلمو حل كنم اما شما فرموديد كه از نظر امنيتي مشكل داره سرعت فعلا مهم نيست واسه من فعلا مهم اينه كه كد من مشكل امنيتيش كجاست و چطور رفع ميشه؟

rana-writes
سه شنبه 08 تیر 1389, 12:03 عصر
سلام
تا من بیام بنویسم جناب raziee (http://barnamenevis.org/forum/member.php?u=95909) خودشون جواب دادن
مشکل کد شما اینه که مستقیما پارامترهاتون رو ارسال میکنین
من یه توضیحاتی براتون نوشتم - البته قبل از جواب دوم جناب raziee (http://barnamenevis.org/forum/member.php?u=95909) بوده ازشون پوزش میخوام - شاید به دردتون بخوره

سلام
این طوری هم میتونین استفاده کنین فرقی با روش قبلی نداره، جناب raziee حتما خودشون براتون توضیح میدن
من شیوه کار خودم رو میگم
شما اول یه StoredProcedure توی بانکتون ایجاد میکنین توی Stored ها میتونین دستورات T_Sql رو بنویسین و یا اگه پارامتری برای پاس دادن داشتین، ازش استفاده کنین
با این Stored که این پایین نوشته شده، میشه توی یه جدول همون عمل Insert رو انجام داد
اول اسم Stored، بعد هم معرفی فیلدهای جدول به همراه نوعشون و در آخر هم دستور Insert
کد StroedProcedure


CREATE PROCEDURE dbo.Ha_InsertPost
(
@UserName nvarchar(10),
@PostTitle nvarchar(200),
@PostContent ntext,
@PostYear nchar(4),
@PostMonth nchar(2),
@PostDay nchar(2),
@PostTemp tinyint,
@SumComment int
)
AS
BEGIN TRANSACTION
INSERT INTO Halgheh_Post
(UserName, PostTitle, PostContent,PostYear,PostMonth, PostDay,PostTemp,SumComment)
VALUES (@UserName, @PostTitle, @PostContent, @PostYear,@PostMonth,@PostDay, @PostTemp,@SumComment)


IF @@ERROR<>0
ROLLBACK TRANSACTION
ELSE
COMMIT TRANSACTION
GO


من تو برنامه هام از کلاس استفاده میکنم رشته ConnectionString که طبیعتا توی وب کانفیگ قرار داره، یه کلاس به اسم ConnectionManager دارم که ارتباط با بانکم رو اونجا انجام میدم
با این کد:


public static SqlConnection ConnectToHalghehDB()
{
string ConnectionString = ConfigurationManager.ConnectionStrings["HalghehConnectionString"].ConnectionString;
SqlConnection connection = newSqlConnection(ConnectionString);
try
{
connection.Open();
}
catch (SqlException)
{
}
return connection;
}


این کدی که براتون مثالش رو میارم مربوط به درج خبر توی یه سایته، کلیه توابعی که با خبر و پست توی سایتم هستن رو توی یه کلاس به اسم PostDataAccess قرار دادم
برای درج پست این تابع رو نوشتم:


public static int AddPost(string UserName, string PostTitle, string PostContent,
string PostYear,string PostMonth,string PostDay, int PostTemp,int SumComment)
{

int roweffect = 0;
using (SqlConnection connection = ConnectionManager.ConnectToHalghehDB())
{

SqlCommand command = newSqlCommand("Ha_InsertPost", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@UserName", SqlDbType.NVarChar).Value = UserName;
command.Parameters.Add("@PostTitle", SqlDbType.NVarChar).Value = PostTitle;
command.Parameters.Add("@PostContent", SqlDbType.NText).Value = PostContent;
command.Parameters.Add("@PostYear", SqlDbType.NVarChar).Value = PostYear;
command.Parameters.Add("@PostMonth", SqlDbType.NVarChar).Value = PostMonth;
command.Parameters.Add("@PostDay", SqlDbType.NVarChar).Value = PostDay;
command.Parameters.Add("@PostTemp", SqlDbType.TinyInt).Value = PostTemp;
command.Parameters.Add("@SumComment", SqlDbType.Int).Value = SumComment;
roweffect = command.ExecuteNonQuery();
}
return roweffect;
}

توی این تابع، اول پارامترها رو معرفی میکنم، بعد SqlCommand رو از نوع StoredProcedure که قبلا تعریف کردم قرار میدم
بعد هم دونه دونه پارامترها رو بهش نسبت میدم
حالا توی صفحه ای که قراره عمل درج انجام بشه اینطوری می نویسم:


int roweffect = PostDataAccess.AddPost(UserName, PostTitle, Content, TxtYear.Text, TxtMonth.Text,
TxtDay.Text, temp, sumcomment);

اگه دوباره سوالی بود بپرسین
موفق باشین

mohsen.nsb44
سه شنبه 08 تیر 1389, 12:12 عصر
سلام
تا من بیام بنویسم جناب raziee (http://barnamenevis.org/forum/member.php?u=95909) خودشون جواب دادن
مشکل کد شما اینه که مستقیما پارامترهاتون رو ارسال میکنین
من یه توضیحاتی براتون نوشتم - البته قبل از جواب دوم جناب raziee (http://barnamenevis.org/forum/member.php?u=95909) بوده ازشون پوزش میخوام - شاید به دردتون بخوره

سلام
این طوری هم میتونین استفاده کنین فرقی با روش قبلی نداره، جناب raziee حتما خودشون براتون توضیح میدن
من شیوه کار خودم رو میگم
شما اول یه StoredProcedure توی بانکتون ایجاد میکنین توی Stored ها میتونین دستورات T_Sql رو بنویسین و یا اگه پارامتری برای پاس دادن داشتین، ازش استفاده کنین
با این Stored که این پایین نوشته شده، میشه توی یه جدول همون عمل Insert رو انجام داد
اول اسم Stored، بعد هم معرفی فیلدهای جدول به همراه نوعشون و در آخر هم دستور Insert
کد StroedProcedure


CREATE PROCEDURE dbo.Ha_InsertPost
(
@UserName nvarchar(10),
@PostTitle nvarchar(200),
@PostContent ntext,
@PostYear nchar(4),
@PostMonth nchar(2),
@PostDay nchar(2),
@PostTemp tinyint,
@SumComment int
)
AS
BEGIN TRANSACTION
INSERT INTO Halgheh_Post
(UserName, PostTitle, PostContent,PostYear,PostMonth, PostDay,PostTemp,SumComment)
VALUES (@UserName, @PostTitle, @PostContent, @PostYear,@PostMonth,@PostDay, @PostTemp,@SumComment)


IF @@ERROR<>0
ROLLBACK TRANSACTION
ELSE
COMMIT TRANSACTION
GO


من تو برنامه هام از کلاس استفاده میکنم رشته ConnectionString که طبیعتا توی وب کانفیگ قرار داره، یه کلاس به اسم ConnectionManager دارم که ارتباط با بانکم رو اونجا انجام میدم
با این کد:


publicstatic SqlConnection ConnectToHalghehDB()
{
string ConnectionString = ConfigurationManager.ConnectionStrings["HalghehConnectionString"].ConnectionString;
SqlConnection connection = newSqlConnection(ConnectionString);
try
{
connection.Open();
}
catch (SqlException)
{
}
return connection;
}


این کدی که براتون مثالش رو میارم مربوط به درج خبر توی یه سایته، کلیه توابعی که با خبر و پست توی سایتم هستن رو توی یه کلاس به اسم PostDataAccess قرار دادم
برای درج پست این تابع رو نوشتم:


public static int AddPost(string UserName, string PostTitle, string PostContent,
string PostYear,string PostMonth,string PostDay, int PostTemp,int SumComment)
{

int roweffect = 0;
using (SqlConnection connection = ConnectionManager.ConnectToHalghehDB())
{

SqlCommand command = newSqlCommand("Ha_InsertPost", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@UserName", SqlDbType.NVarChar).Value = UserName;
command.Parameters.Add("@PostTitle", SqlDbType.NVarChar).Value = PostTitle;
command.Parameters.Add("@PostContent", SqlDbType.NText).Value = PostContent;
command.Parameters.Add("@PostYear", SqlDbType.NVarChar).Value = PostYear;
command.Parameters.Add("@PostMonth", SqlDbType.NVarChar).Value = PostMonth;
command.Parameters.Add("@PostDay", SqlDbType.NVarChar).Value = PostDay;
command.Parameters.Add("@PostTemp", SqlDbType.TinyInt).Value = PostTemp;
command.Parameters.Add("@SumComment", SqlDbType.Int).Value = SumComment;
roweffect = command.ExecuteNonQuery();
}
return roweffect;
}

توی این تابع، اول پارامترها رو معرفی میکنم، بعد SqlCommand رو از نوع StoredProcedure که قبلا تعریف کردم قرار میدم
بعد هم دونه دونه پارامترها رو بهش نسبت میدم
حالا توی صفحه ای که قراره عمل درج انجام بشه اینطوری می نویسم:


int roweffect = PostDataAccess.AddPost(UserName, PostTitle, Content, TxtYear.Text, TxtMonth.Text,
TxtDay.Text, temp, sumcomment);

اگه دوباره سوالی بود بپرسین
موفق باشین
ممنون از زحمتي كه كشيديد من كد هاتونو بررسي ميكنم تو سيستم پياده مي كنم اگه به مشكلي بر خوردم دوباره مزاحمتون مي شم

mohsen.nsb44
سه شنبه 08 تیر 1389, 12:15 عصر
AS
BEGIN TRANSACTION
اين قسمت تو StroedProcedure و اين قسمت IF @@ERROR<>0
ROLLBACK TRANSACTION
ELSE
COMMIT TRANSACTION
GO
چيكار مي كنه؟

raziee
سه شنبه 08 تیر 1389, 12:18 عصر
من مشكل زيادي داشتم واسه ثبت يك ركورد با استفاده از پارامتر ها الان تونستم بوسيله كد بالا مشكلمو حل كنم اما شما فرموديد كه از نظر امنيتي مشكل داره سرعت فعلا مهم نيست واسه من فعلا مهم اينه كه كد من مشكل امنيتيش كجاست و چطور رفع ميشه؟
این تاپیک رو ببینید دوست من.
http://barnamenevis.org/forum/showpost.php?p=450085&postcount=5

rana-writes
سه شنبه 08 تیر 1389, 13:49 عصر
BEGIN TRANSACTION
اين قسمت تو StroedProcedure و اين قسمت IF @@ERROR<>0
ROLLBACK TRANSACTION
ELSE
COMMIT TRANSACTION
GO


سلام دوباره توی بخش Help برنامه SqlServer اینطوری نوشته:
When Microsoft® SQL Server™ completes the execution of a Transact-SQL statement, @@ERROR is set to 0 if the statement executed successfully. If an error occurs, an error message is returned
یعنی وقتی یه دستور TSql اجرا میشه، اگر درست اجرا بشه، مقدار صفر برمیگرده، در غیر اینصورت شماره خطا برمیگرده
خب تا اینجا وقتی میگیم


IF @@ERROR<>0

یعنی دستور ما اگر به هر دلیلی اجرا نشه، یعنی دارای خطا باشه:
کاری که انجام بده این باشه


ROLLBACK TRANSACTION

یعنی بره به ابتدای Transactionباز هم طبق چیزی که بخش Help میگه:
Rolls back an explicit or implicit transaction to the beginning of the transaction, or to a savepoint inside a transaction

این بخش هم


ELSE COMMIT TRANSACTION

که در غیر اینصورت If بالاست، یعنی هیچ خطایی برنگرده و T_Sql درست باشه
Marks the end of a successful implicit or user-defined transaction.
در اینصورت Transaction اجرا بشه
Begin Transaction هم که پرسیده بودین، ابتدای دستورات T_Sql قرار میگیره
امیدوارم مفید بوده باشه
موفق باشین

mohsen.nsb44
سه شنبه 08 تیر 1389, 14:07 عصر
BEGIN TRANSACTION درباره اين قسمت بيشتر توضيح مي دين؟
ممنون از راهنماييتون خيلي زحمت كشيديد

rana-writes
سه شنبه 08 تیر 1389, 14:18 عصر
BEGIN TRANSACTION درباره اين قسمت بيشتر توضيح مي دين؟
ممنون از راهنماييتون خيلي زحمت كشيديد

واضحه ،شروع دستورات TSql رو این عبارت مشخص میکنیم
مثل آکولاد که توی C# نشون دهنده شروع یه تابعه
راهنمای SqlServer هم اینو میگه:
Marks the starting point of an explicit, local transaction.

rana-writes
سه شنبه 08 تیر 1389, 14:26 عصر
یه مطلب مهم دیگه
این شکل استفاده کردن فقط برای ثبت توی بانک نیست
برای کلیه دستوراتی که با بانک سروکار داره، آپدیت، حذف، Select و ..
میتونین از ارسال پارامتر استفاده کنین
حذف و آپدیت دقیقا شبیه درج عمل میکنه
اما برای خوندن از بانک یا همون Select یه کم مدلش فرق میکنه که اگه خواستین براتون میذارم
موفق باشین

mohsen.nsb44
سه شنبه 08 تیر 1389, 14:37 عصر
یه مطلب مهم دیگه
این شکل استفاده کردن فقط برای ثبت توی بانک نیست
برای کلیه دستوراتی که با بانک سروکار داره، آپدیت، حذف، Select و ..
میتونین از ارسال پارامتر استفاده کنین
حذف و آپدیت دقیقا شبیه درج عمل میکنه
اما برای خوندن از بانک یا همون Select یه کم مدلش فرق میکنه که اگه خواستین براتون میذارم
موفق باشین
ممنون دوست عزيز فعلا نيازي به دستور سلكت ندارم الان كارم تموم ميشه ميرم خونه كد رو امتحان مي كنم اگه مشكلي داشتم باز عنوان مي كنم خيلي زحمت كشيديد ممنون از لطفتون

mohsen.nsb44
سه شنبه 08 تیر 1389, 16:24 عصر
سلام دوست عزیز چند سوال واسه من پیش اومده
1اینکه تو کد هاتون کجا نام دیتابیس خودمو باید قرار بدم
2برای درج رکورد تو کد هاتون کجا نام جدولم رو باید قرار بدم
3 من از سی شارپ 2005 استفاده میکنم موقع تایپ int roweffect = PostDataAccess.AddPost ،PostDataAccess وجود ندارد ایا باید namespace ی اضافه کرد که بشه از این گزینه استفاده کرد؟

raziee
سه شنبه 08 تیر 1389, 17:22 عصر
با اجازه ی rana-writes


1اینکه تو کد هاتون کجا نام دیتابیس خودمو باید قرار بدم

string ConnectionString = ConfigurationManager.ConnectionStrings["HalghehConnectionString"].ConnectionString;


برای درج رکورد تو کد هاتون کجا نام جدولم رو باید قرار بدم
در SP مینویسید و اون SPرو صدا میزنید.

من از سی شارپ 2005 استفاده میکنم موقع تایپ int roweffect = PostDataAccess.AddPost ،PostDataAccess وجود ندارد ایا باید namespace ی اضافه کرد که بشه از این گزینه استفاده کرد؟
اون کلاسی هست که دوستمون خودشون نوشتند.:اشتباه: