انجام Insert,Select,Update و Delete در ASP.Net
یکشنبه 19 مهر 1394در این مقاله خواهیم دید که چگونه یک برنامه ASP.NET با چهار عمل اصلی CRUD و همین طور صفحه ورود و ثبت کاربر داشته باشیم. در برنامه ما از پروسیجر و لایه ها استفاده می کنیم.
قبل از اینکه بخواهیم یک برنامه ASP.NET ایجاد کنیم، کسانی که به تازگی شروع به کار کرده اند، ممکن است سوالاتی ازاین قبیل داشته باشند:
1- چگونه یک صفحه ورود ایجاد کنیم؟
2- چگونه یک کاربر معتبر را بررسی کرده و به صفحه اصلی انتقال دهیم؟
3-چگونه نام کاربر وارد شده به سایت را در تمام صفحات نمایش دهیم؟
4-چگونه اطلاعات را grid متصل کنیم؟
5-چگونه اطلاعات را جستجو کرده و در grid نمایش دهیم؟
6-چگونه از یک gridview اطلاعات را در بانک اطلاعاتی Insert,Update,Delete و Select نماییم؟
7-چگونه یک ASP.NET Web Application ساده بنویسیم؟
8-چگونگی احراز هویت و دادن مجوز
در این آموزش می خواهیم برای تمام سوالات مطرح شده در بالا یک برنامه ساده ASP.Net به همراه صفحه Login و صفحه Main ایجاد کنیم تا اعمالی نظیر چهار عمل اصلی CRUD و قسمت search و اعتبارسنجی با javascript و پروسیجر داشته باشد.
در ابتدا بدانیم که CRUD چیست؟ CRUD مخفف کلمات زیر می باشد:
Create: درج داده در بانک اطلاعاتی (insert/add)
Read: انتخاب داده در بانک اطلاعاتی (Select)
Update: بروز رسانی داده در بانک اطلاعاتی(edit/update)
Delete: پاک کردن اطلاعات از بانک اطلاعاتی
چرا ما به CRUD نیاز داریم و در کجا از آن استفاده کنیم؟
ما دو نوع توسعه برنامه داریم. یکی FrontEnd و دیگری BachEnd.
یک Frontend می تواند یک برنامه وب، دسکتاپ یا برنامه موبایل باشد. یک برنامه می تواند باهریک از زبان ها مانند #C یا VB.Net ایجاد و توسعه یابد. یک BackEnd یک بانک اطلاعاتی مانند Access,MySQL, SQL Server, Oracle می باشد.
frontend برای ارائه اطلاعات و backend برای ذخیره اطلاعات می باشد. برای ارتباط backend مانند sql با frontend مانند ASP.Net، ما از ADO.Net استفاده می کنیم. با استفاده از اشیاء ADO.Net مانند Connection,Command,Data Set, Data Adapter و خیلی موارد دیگر می توانیم عملیات CRUD را انجام دهیم.
اگر ما یک بانک اطلاعاتی SQL داشته باشیم که با ADO.Net به برنامه ASP.Net متصل شده باشد، برای بدست آوردن اطلاعات از بانک اطلاعاتی نیاز به select اطلاعات از بانک و نمایش آنها در برنامه داریم. همینطور نیاز به درج داده های وارد شده توسط کاربر در بانک داریم. همینطور نیاز به پاک کردن، ویرایش و بروز رسانی داده های تغییر داده شده توسط کاربر داریم. تمام انجام این عملیات ایجاد، درج، حذف و نمایش از بانک در برنامه، CRUD نام دارد.
معماری N-Tier
در توسعه یک برنامه، Tier یک لایه نامیده می شود. تصویر زیر را ببینیم:
در اینجا لایه ها چیزی جز یک کلاس نیستند.
UI: رابط کاربری که در آن کاربر ورودی های خود را برای ذخیره شدن وارد می کند.
Business Logic Layer: در اینجا لایه Business Logic یک کلاس است. از فرم UI همه ورودی ها ازسمت کاربر را به کلاس Business Logic به عنوان یک شی ارسال می کنیم.
Data Access Layer: تمام پارامترهای درون لایه Business Logic را به لایه Data Access ارسال می کنیم. این کلاس از اشیا ADO.Net (مانند Command،که command یک متن کوئری یا پروسیجر است. Execute NonQuery کار درج، بروزرسانی و حذف را انجام می دهد. ExecuteDataset دستور select را بازمی گرداند و دستور ExecuteScalar یک داده را برمی گرداند.) استفاده می کند.
احراز هویت و دادن مجوز (Authentication and Authorization)
احراز هویت: بررسی برای معتبر بودن کاربر. در اینجا مساله این است که چگونه معتبر بودن یا نبودن کاربر بررسی می شود. هنگامی که یک کاربر برای اولین بار وارد سایتی می شود، در آن ثبت نام خواهد کرد و تمام اطلاعات آن در بانک اطلاعاتی وبسایت ذخیره خواهد شد. هنگامی که کاربر اطلاعات خود را وارد می کند، اطلاعات با اطلاعات بانک اطلاعاتی بررسی می شود. اگر نام کاربری و رمز عبوری که وارد کرده است، با اطلاعات موجود در بانک مطابقت داشته باشد، او یک کاربر معتبر بوده و به صفحه اصلی وبسایت منتقل می شود و اگر مطابقت نداشته باشد، در صفحه ورود یک پیغام مانند "نام کاربری یا رمز عبور صحیح نمی باشد" دریافت خواهد کرد. تمام فرآیند بررسی معتبر یا نبودن کاربر برای دسترسی به وبسایت را احراز هویت (Authentication) می نامند.
در ASP.NET می توانیم از هر متدی برای اعتبارسنجی کاربر استفاده کنیم.
Windows Authentication : از local Windows user برای بررسی اعتبار استفاده می شود.
Forms Authentication : با استفاده از form authentication می توانیم کد خود را نوشته و اعتبار کاربر را بررسی کنیم. جزئیات کاربر شناخته شده در کوکی کامپیوتر کاربر ذخیره خواهد شد.
در اینجا ما در مقاله خود از Forms Authentication استفاده می کنیم. برای استفاده از Forms Authentication در Web.Config مد Authentication را برای Forms تنظیم می کنیم.
تنظیم Login Page URL و Default Page URL در وب سایت
Default URL:
بعد از شناسایی کاربر در صفحه ورود، به صفحه defaultURL منتقل خواهد شد. برای مثال ما صفحه Default.ASPX را داریم.
<authentication mode="Forms"><forms defaulturl="Default.aspx" loginurl="~/Account/Login.aspx" slidingexpiration="true" timeout="2880" /></authentication>
Passport authentication: (احراز هویت گذرنامه) بر اساس Microsoft Passport در یک وبسایت مانند Hotmail و غیره می باشد. دراینجا احراز هویت کاربر از گذرنامه تایید خواهد شد.
Authorization: هنگامی که کاربر تایید شد، نیاز دارد که به صفحه ای متناسب با role خود تعریف شود. برای مثال هنگامی که Admin وارد می شود، به صفحه مدیریت منتقل می شود و اگر مثلا یک حسابدار وارد شد، به صفحه حسابرسی خود منتقل شود. و اگر یک کاربر نهایی وارد سایت شد، به صفحه خاص خودش منتقل شود.
در ASP.NET ما با استفاده از Authorization (دادن مجوز) کاربران را با توجه به نقشی که دارند، به صفحه مناسب هدایت می کنیم.
صفحه پیش فرض login در Asp.net
بصورت پیشفرض می توانیم صفحه ورود و صفحه ثبت نام کاربر خود ASP.Net را ببینیم و از آن ها برای توسعه وبسایت خود استفاده کنیم. در زیر تصویر پوشه App_Data را می بینیم.
فایل Web.Config: درون این فایل، می توانیم connection string را ببینیم که نام فایل بانک اطلاعاتی در آن قرار می گیرد. این فایل می تواند به صورت local درون پوشه App_Data قرار گیرد.
هنگامی که وبسایت ASP.Net را اجرا می کنیم، با کلیک بر روی قسمت ورود و ثبت نام، یک کاربر جدید برای وبسایت مان ایجاد خواهیم کرد. می توانیم بانکی را که ایجاد کرده ایم را ببینیم. تمام اطلاعات کاربر درون این بانک ذخیره می شود.
استفاده از سیستم login پیشفرض ASP.Net می تواند مفید باشد. سیستم ورود ASP.Net یک راه امن تر برای نگهداری اطلاعات کاربر و رمز عبور می باشد.
aspnetdb in SQL Server DB
ما می توانیم در SQL Server بانک اطلاعاتی ایجاد کرده و از آن به جای دیتابیس محلی استفاده کنیم.
استفاده از کد
برنامه ASP.NET web application خود را ایجاد کنید.
نیاز داریم که تمام کلاس های لازم را درون پوشه App_Code در وبسایت ایجاد کنیم. زمانیکه یک پروژه جدید وب ایجاد می کنیم نیاز به ساخت یک فولدر می باشد. زمانیکه App_code درون این پوشه است می توانیم یک زیرپوشه ایجاد کرده و تمام کلاس ها را درون آن اضافه کنیم.
برای درک آسان در برنامه دو پوشه به نام های BIZ و DAL ایجاد کرده ایم. ما دو لایه داریم. یکی لایه BIZ و دیگری لایه DAL می باشد.
در پوشه DAL موارد زیر را داریم:
کلاس SQL Helper: که کلاس DAL می باشد که می توانیم عملیات CRUD را انجام دهیم.
کلاس BixBase: این کلاس برای اضافه کردن و بدست آوردن پارامترهای SQL برای آرایه در کلاس Business ارث بری خواهد داشت.
در پوشه BIZ می توانیم تمام کلاس های Business را ایجاد کنیم.
برای مثال ما دو کلاس ایجاد کرده ایم. یکی برای صفحه Login و یکی برای صفحه اصلی.
مرحله بعد ایجاد جداول درون بانک اطلاعاتی برای انجام عملیات CRUD می باشد.
در برنامه یک جدول اصلی داریم.
Connection String: برای سایر جداول بانک اطلاعاتی می توانیم Connection String را تنظیم کنیم.
<connectionStrings><add name="shanu" connectionString="Data Source=YOURServer;Initial Catalog=YOURDB;Persist Security Info=True;User ID=YOURUID;Password=yourpwd" providerName="System.Data.SqlClient"/> <add name="ApplicationServices" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient"/> <!--<add name="ApplicationServices" connectionString="Data Source=YOURServer;Initial Catalog=aspnetdb;user id=YOURUID;password=yourpwd;Integrated Security=True" providerName="System.Data.SqlClient"/>--></connectionStrings>
ایجاد جدول
ما یک جدول اصلی کاربر ایجاد خواهیم کرد که برای تصدیق ورود می باشد. داخل آن مقداریداده وارد می کنیم.
CREATE TABLE [dbo].[ItemMasters]( [Item_Code] [nvarchar](50) NOT NULL, [Item_Name] [nvarchar](100) NOT NULL, [Price] [int] NOT NULL, [TAX1] [int] NOT NULL, [Discount] [int] NOT NULL, [Description] [nvarchar](200) NOT NULL, [IN_DATE] [datetime] NOT NULL, [IN_USR_ID] [nvarchar](50) NOT NULL, [UP_DATE] [datetime] NOT NULL, [UP_USR_ID] [nvarchar](50) NOT NULL, CONSTRAINT [PK_ItemMasters] PRIMARY KEY CLUSTERED ( [Item_Code] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
صفحه ورود
در زیر تصویر صفحه ورود را می بینید.
ما از صفحه login پیشفرض ASP.Net استفاده می کنیم. در اینجا یک لینک برای ایجاد کاربر جدید را مشاهده می کنید. وقتی کاربر روی این لینک کلیک می کند، صفحه ایجاد کاربر باز خواهد شد.
زمانی که کاربر اطلاعات خود را ثبت کرد، آن اطلاعات در فایل aspnetdb ذخیره خواهند شد.
صفحه اصلی (Main Page)
اکنون صفحه login تکمیل شده و می خواهیم صفحه Main را طراحی کنیم.
در تصویر زیر می توانید صفحه اصلی ما را ببینید.
در برنامه از MasterPage استفاده کردیم تا بتوانیم جزئیات را در تمام صفحات نمایش دهیم. در صفحه Master از LoginName و LoginStatus استفاده می کنیم. این برای نمایش کاربر تصدیق شده در تمام صفحات است.
در صفحه Master دو منو داریم. صفحه اصلی و مدیریت بخش ها. در منوی مدیریت بخش ها، کاربر می تواند بخش ها را جستجو کرده و کارهای insert, Edit,delete را انجام دهد.
گزینه جستجو
در صفحه متد init ابتدا احراز هویت کاربران بررسی می شود. اگر کاربر اعتبار سنجی نشده بود، به صفحه Login هدایت می شود.
protected override void OnInit(EventArgs e) { base.OnInit(e); if (!this.Page.User.Identity.IsAuthenticated) { FormsAuthentication.RedirectToLoginPage(); } }
در این مرحله می بینیم که چگونه ورودی کاربر جستجو شده و نتیجه در grid نمایش داده می شود.
جستجو و انتخاب (Search/Select)
در رویداد کلیک دکمه Search: پارامتر به کلاس BIZ فرستاده می شود و از کلاس BIZ به کلاس DAL فرستاده می شود و نتیجه را بعنوان یک dataset گرفته و با GridView اتصال می دهد.
کاربر می تواند براساس کد یا نام جستجو را انجام دهد. اگر هر ورودی خالی باشد تمام رکوردهای دیتابیس با استفاده از executeDataset برگشت داده خواهند شد.
protected void btnSearch_Click(object sender, ImageClickEventArgs e) { SelectList(); } //This Method is used for the search result bind in Grid private void SelectList() { SortedDictionary<string, string=""> sd = new SortedDictionary<string, string="">() { }; sd.Add("@pTYPE", "S1"); sd.Add("@Item_Code", txtSitemCDE.Text.Trim()); sd.Add("@Item_Name", txtSItemNme.Text.Trim()); DataSet ds = new DataSet(); ds = new ShanuCRUDBizClass().SelectList(sd); GridView1.DataSource = ds; GridView1.DataBind(); } </string,></string,>
پروسیجر CRUD
برای صفحه اصلی تنها یک پروسیجر ایجاد می کنیم تا چهار عمل CRUD را برای ما انجام دهد.پارامترهای لازم را به صورت زیر به پروسیجر ارسال می کنیم.
pType=”S1”: برای جستجو
pType=”S2”: برای یافتن کد item بعدی و برگرداندن مقدار
pType=”I3”: برای درج رکوردها
pType=”U4”: برای به روز رسانی رکورد
pType=”D5”: برای حذف رکورد
ALTER PROCEDURE [dbo].[USP_Item_CRUD] ( @pTYPE NVARCHAR(02) = '', @Item_Code NVARCHAR(50) = '', @Item_Name NVARCHAR(50) = '', @Price INT=0 , @TAX1 INT=0 , @Discount INT=0 , @Description NVARCHAR(50) = '', @USR_Name NVARCHAR(50) = '' ) AS BEGIN Declare @maxItemCode varchar(30)=''; IF @pTYPE = 'S1' GOTO S1_RTN -- Select Query ELSE IF @pTYPE = 'S2' GOTO S2_RTN -- Select for ExceuteScalar Query ELSE IF @pTYPE = 'I3' GOTO I3_RTN -- Insert Query ELSE IF @pTYPE = 'U4' GOTO U4_RTN -- Update Query ELSE IF @pTYPE = 'D5' GOTO D5_RTN -- Delete Query RETURN --Select S1_RTN: BEGIN Select Item_Code, Item_Name, Price, TAX1, Discount, Description, UP_USR_ID as user_Name FROM ItemMasters WHERE Item_Code like @Item_Code +'%' AND Item_Name like @Item_Name +'%' ORDER BY Item_Name, Item_Code RETURN END --Select S2_RTN: BEGIN Set @maxItemCode='Item00' + Convert(Varchar(10),(Select MAX(RIGHT(ITEM_CODE, 3))+1 from itemMasters)) select @maxItemCode ItemCODE RETURN END --Insert I3_RTN: BEGIN IF NOT EXISTS (SELECT * FROM ItemMasters WHERE Item_Name=@Item_Name) BEGIN INSERT INTO [ItemMasters] ([Item_Code],[Item_Name],[Price],[TAX1],[Discount],[Description],[IN_DATE] ,[IN_USR_ID],[UP_DATE],[UP_USR_ID]) VALUES (@Item_Code,@Item_Name,@Price,@TAX1,@Discount,@Description,GETDATE(),@USR_Name ,GETDATE(),@USR_Name) SET @Item_Code=''; SET @Item_Name=''; GOTO S1_RTN END ELSE BEGIN Select 'Exists' END RETURN END --Update U4_RTN: BEGIN IF EXISTS (SELECT * FROM ItemMasters WHERE Item_Code=@Item_Code) BEGIN UPDATE [ItemMasters] SET [Item_Name]=@Item_Name, [Price]=@Price, [TAX1]=@TAX1, [Discount]=@Discount, [Description]=@Description, [UP_DATE]=GETDATE(), [UP_USR_ID]=@USR_Name WHERE Item_Code=@Item_Code SET @Item_Code=''; SET @Item_Name=''; GOTO S1_RTN END RETURN END --Delete D5_RTN: BEGIN DELETE FROM [ItemMasters] WHERE Item_Code=@Item_Code END END
اضافه کردن item جدید : کاربر می تواند داده های خود را وارد کرده تا یک رکورد جدید در بانک اطلاعاتی اضافه و ذخیره شود.
هنگامیکه کاربر روی کلید افزودن کلیک می کند، یک کد جدید در بانک تولید شده و یک تک مقدار با استفاده از Execute Scalar برگردانده می شود. بطور پیشفرض New و Edit بصورت پنهان می باشند و هنگامی که کاربر روی روی دکمه کلیک کرد، جداول برای افزودن و ویرایش نمایان خواهد شد.
/Here used the Datareader to get the max itemCode and display in Item Code Textbox protected void btnAdd_Click(object sender, ImageClickEventArgs e) { if (hidsaveType.Value == "Edit") { return; } txtitemCode.Text = new ShanuCRUDBizClass().SelectScalar("S2"); tdADD.Visible = true; }
در رویداد کلیک دکمه ذخیره، تمام ورودی ها را دریافت کرده و پارامترها به لایه BAL ارسال خواهند شد و از BAL برای درج رکورد جدید با استفاده از ExecuteNonQuery به لایه DAL ارسال خواهد شد.
//Save Button Click protected void btnSave_Click(object sender, ImageClickEventArgs e) { if (hidsaveType.Value == "Add") { InsertCall("I3"); } else if(hidsaveType.Value == "Edit") { UpdateCall("U4"); } } //This method is used for both Insert and Update Funtionc private void InsertCall(String PTYPE) { SortedDictionary<string, string=""> sd = new SortedDictionary<string, string="">() { }; sd.Add("@pTYPE", PTYPE); sd.Add("@Item_Code", txtitemCode.Text.Trim()); sd.Add("@Item_Name", txtitemName.Text.Trim()); sd.Add("@Price", txtPrice.Text.Trim()); sd.Add("@TAX1", txtTax.Text.Trim()); sd.Add("@Discount", txtDiscount.Text.Trim()); sd.Add("@Description", txtdescription.Text.Trim()); sd.Add("@USR_Name", User.Identity.Name); DataSet ds = new DataSet(); ds = new ShanuCRUDBizClass().SelectList(sd); if (ds.Tables.Count > 0) { if (ds.Tables[0].Rows[0].ItemArray[0].ToString() == "Exists") { Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "alert", "alert('Item already Exist !')", true); txtitemName.Focus(); } } else { GridView1.DataSource = ds; GridView1.DataBind(); clearControls(); } } private void UpdateCall(String PTYPE) { SortedDictionary<string, string=""> sd = new SortedDictionary<string, string="">() { }; sd.Add("@pTYPE", PTYPE); sd.Add("@Item_Code", txtitemCode.Text.Trim()); sd.Add("@Item_Name", txtitemName.Text.Trim()); sd.Add("@Price", txtPrice.Text.Trim()); sd.Add("@TAX1", txtTax.Text.Trim()); sd.Add("@Discount", txtDiscount.Text.Trim()); sd.Add("@Description", txtdescription.Text.Trim()); sd.Add("@USR_Name", User.Identity.Name); DataSet ds = new DataSet(); ds = new ShanuCRUDBizClass().SelectList(sd); GridView1.DataSource = ds; GridView1.DataBind(); clearControls(); } </string,></string,></string,></string,>
code behind بسیار ساده به نظر می رسد زیرا لایه Business و بانک اطلاعاتی در دو کلاس از یکدیگر جدا شده اند.
در GridView از TemplateFiled برای add,edite و delete برای دکمه image استفاده می کنیم. با استفاده از Gridview RowCommand بررسی می کنیم که کدام یک از دکمه ها کلیک شده است تا بتوانیم کار مورد نظر را انجام دهیم.
می توانید مشاهده کنید که در Gridview Rowcommand نام دستور برای تشخیص اینکه دستور حذف یا ویرایش است، بررسی خواهد شد. اگر دکمه ویرایش عکس بررسی شده باشد، سپس index سطر کلیک شده را به دست می آوریم. با استفاده از GridViewRow تمام بخش های سطر بدست آمده و در textbox نمایش داده می شوند تا کاربر بتواند تغییرات را انجام دهد.
// Grid Row command to do Edit and delete Operations protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { clearControls(); if (e.CommandName == "edits") { hidsaveType.Value = "Edit"; // To get the Current Row Number GridViewRow row = (GridViewRow)((Control)e.CommandSource).NamingContainer; int rowIndex = row.RowIndex; txtitemCode.Text = row.Cells[2].Text; txtitemName.Text = row.Cells[3].Text; txtPrice.Text = row.Cells[4].Text; txtTax.Text = row.Cells[5].Text; txtDiscount.Text = row.Cells[6].Text; txtdescription.Text = row.Cells[7].Text; tdADD.Visible = true; btnAdd.ImageUrl = "~/Images/btnEdit.jpg"; } else if (e.CommandName == "deletes") { // To get the Current Row Number GridViewRow row = (GridViewRow)((Control)e.CommandSource).NamingContainer; int rowIndex = row.RowIndex; DeleteItem(row.Cells[2].Text); } }
حذف رکوردها
مانند ویرایش، با RowCommand دستور حذف، با کلیک شدن بررسی خواهد شد. که در اینصورت تابع برای انجام عملیات حذف فراخوانی خواهد شد.
// This method will delete the selected Rocord from DB private void DeleteItem(String ItemCode) { ShanuCRUDBizClass obj = new ShanuCRUDBizClass(); obj.CRUD_Deletes(ItemCode); SelectList(); }
متد delete کلاس BIZ: در اینجا از ExecuteNoneQuery برای حذف رکوردها از بانک استفاده می کنیم. در متد deleteItems بعد از یک حذف، متد selectList فراخوانی خواهد شد تا مجددا نتیجه را به GridView متصل (bind) کند.
public void CRUD_Deletes(string ItemCode) { try { SqlParameter[] paramArray = new SqlParameter[] { }; AddParameter(ref paramArray, "@pTYPE", "D5"); AddParameter(ref paramArray, "@Item_Code", ItemCode); SqlHelper.ExecuteNonQuery(ConnectionString, CommandType.StoredProcedure, "USP_Item_CRUD", paramArray); } catch (Exception ex) { throw ex; } }
نکته: برای اجرای برنامه، یک جدول ایجاد کرده و مقداری داده درون آن وارد کنید. می توانید فایل اجرایی بانک اطلاعاتی برنامه را از قسمت فایل ضمیمه دانلود کنید. بعد از ساخت جدول، درون برنامه ASP فایل web.config را یافته و نام server و بانک اطلاعاتی و نام کاربری و رمز عبور بانک اطلاعاتی را تغییر داده و تطابق دهید.
مراحل اجرای برنامه:
ابتدا فایل دانلود شده را از حالت zip خارج کنید.
1- ویژوال استدیو را باز کرده و گزینه open web site را انتخاب کنید
پوشه پروژه را انتخاب کنید.
2- اسکریپت های بانک اطلاعاتی را اجرا کنید.
3- در برنامه درون ASP.Net فایل web.config را باز کرده و تغیرات گفته شده را درون connection string ایجاد کنید.
4- برنامه را اجرا کنید.
امیدوارم این مقاله بتواند برای شما مفید باشد.
- ASP.net
- 8k بازدید
- 15 تشکر