انشاء السجلات في ADO.NET in ASP.NET Core Application

-

بنتعلم في هذا الدرس كيفية تطبيق العمليات CRUD في Net Core.  وموضوعنا في هذا الدرس كيف ممكن نضيف data في قواعد البيانات Create Records ،بنعمل View لادخال البيانات وقراءتها وبعدها بنعرض البيانات من قاعدة البيانات في View ثاني 

تمام سنقوم هنا بإنشاء شاشة خاصة لتسجيل طالب جديد في قاعدة البيانات ثم عرض جميع الطلاب بشاشة مستقلة.

بنكمل شغل على مشروعنا السابق StudentAcademy 

تأكد من وجود class في المشروع باسم StudentsModel إذا لم تقم بذلك من قبل انتقل الى مجلد Models ومن ثم أضف class جديد باسم StudentsModel

وبعد هيك نضيف الكود التالي:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace StudentsAcademy.Models
{
    public class StudentsModel
    {
        public int StudentID { get; set; }
        public string StudentNo { get; set; }
        [Required(ErrorMessage = "Please enter name")]
        [StringLength(150)]
        public string FullName { get; set; }
        [DataType(DataType.Date)]
        public DateTime Birthday { get; set; }
        public int Gender { get; set; }
        public int Nationality { get; set; }
        public string Address { get; set; }
        [Required(ErrorMessage = "Please enter User Name")]
        [StringLength(20)] 
        public string UserName { get; set; }
        [Required(ErrorMessage = "Please enter Password")]
        [StringLength(20)]
        [DataType(DataType.Password)]
        public string Password { get; set; }
        [Required(ErrorMessage = "Confirm Password is required")]
        [DataType(DataType.Password)]
        [Compare("Password")]
        public string ConfirmPassword { get; set;}
        [Required(ErrorMessage = "Please enter Email")]
        [RegularExpression("^[a-z0-9_+-]+(.[a-z0-9_+-]+)*@[a-z0-9-]+(.[a-z0-9]+)*.([a-z]{2,4})$", ErrorMessage = "Invalid email format.")]
        [StringLength(20)]
        public string Email { get; set; }
        [Required(ErrorMessage = "Mobile is required")]
        [RegularExpression(@"d{10}", ErrorMessage = "Please enter 10 digit Mobile No.")]
        public string Mobile { get; set; }
        public string Note { get; set; }
        public DateTime CreatedDate { get; set; }
        public DateTime CurrentDate { get; set; }
        public PaymentModel Payment { get; set; }
        public Address StudentAddress { get; set; }
    }
}

لاحظ ان اضفنا الكود System.ComponentModel.DataAnnotations الي هو عبارة عن Namespace لغرض اجراء validation في شاشة التسجيل.

والتالي امثلة على الاكواد الخاصة ب validation 




Attribute validation 
الوصف
Required

تستخدم في حال كان المطلوب ان يكون الحقل اجباري

طريقة الكتابة 

[Required(ErrorMessage = "Please enter name")]

في الكود الاسبق طبقناها على FullName

StringLength

تستخدم عندما يكون المطلوب ان يكون طول هذا الحقل لا يجب ان يتجاوز قيمة محددة طريقة الكتابة 

[StringLength(150)] 

هنا اقصى طول مسموح هو  150 حرف 

DataType

يستخدم مع اناع محدده مثل (كلمة مرور ـ ايميل – نص – HTML)طريقة الكتابة 

[DataType(DataType.Password)]

RegularExpression

تستخدم للتعامل مع تعابير محدده بحيث يجب ان يدخل في هذا الحقل. مثل البريد الإلكتروني ، الموقع الإلكتروني

الكود التالي خاص في البريد الإلكتروني

[RegularExpression("^[a-z0-9_+-]+(.[a-z0-9_+-]+)*@[a-z0-9-]+(.[a-z0-9]+)*.([a-z]{2,4})$", ErrorMessage = "Invalid email format.")] 

للمزيد حول هذه DataAnnotations انقر فوق الرابط DataAnnotations


تمام هيك بنكون جهزنا Model. 

الان نعمل على انشاء Controller 

انتقل الى ملف StudentsController في مجلد Controllers، وفي حال ما كان موجد قم بإضافته بالنقر يمين فوق مجلد Controllers ثم اختر Add- New Controller 


تأكد من وجود action method باسم NewStudent من نوع HTTP GET. إذا لم يكن موجود أضف الكود التالي: 

public IActionResult NewStudent()
        {
            return View();
        }

الان باقي نجهز View الي من خلالو بنعمل على ادخال بيانات الطالب.

لذا تأكد من وجود View باسم NewStudent وفي حال ما كان موجود، لازم تضيف View جديدة تسمى NewStudent.cshtml داخل مجلد Views ➤ Students

للتكير اسم View لازم يكون نفس اسم action في controller ، ولاضافة View بتم عن طريق النقر يمين فوق action وبنختار Add New View . 


وأضف الكود أدناه إليه

@model StudentsModel
@{
    Layout = null;
}
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
@*Welcome ,@TempData["UserName"]*@
    Welcome,@HttpContextAccessor.HttpContext.Session.GetString("UserName")
    <hr />
    <div class="container">
        <form id="external-account" asp-page="" asp-route-returnUrl="" method="post" class="form-horizontal">
            <div class="form-group">
                <label>FullName:</label>
                <input class="form-control" asp-for="FullName" />
                <span asp-validation-for="FullName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Birthday:</label>
                <input class="form-control" asp-for="Birthday" />
                <span asp-validation-for="Birthday" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Gender:</label>
                <select class="form-control" asp-for="Gender">
                    <option value="M">Male</option>
                    <option value="F">Female</option>
                </select>
                <span asp-validation-for="Gender" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Nationality:</label>
                <select class="form-control" asp-for="Nationality">
                    <option value="M">Jordan</option>
                    <option value="F">Saudi Aribae</option>
                    <option value="F">UAE</option>
                </select>
                <span asp-validation-for="Nationality" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Address:</label>
                <input class="form-control" asp-for="Address" />
                <span asp-validation-for="Address" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>UserName:</label>
                <input class="form-control" asp-for="UserName" />
                <span asp-validation-for="UserName" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Password:</label>
                <input class="form-control" asp-for="Password" />
                <span asp-validation-for="Password" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Email:</label>
                <input class="form-control" asp-for="Email" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Mobile:</label>
                <input class="form-control" asp-for="Mobile" />
                <span asp-validation-for="Mobile" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label>Note:</label>
                <input class="form-control" asp-for="Note" />
                <span asp-validation-for="Note" class="text-danger"></span>
            </div>
            <button class="btn btn-primary" type="submit">Submit</button>
        </form>
    </div>
    @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }

تمام 

في هذا View أضفنا رابط لملف bootstrap CSS في قسم head  بهذف عرض ال View بشكل مرتب وجميل :

<link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />

تأخذ View هذه model من نوع StudentsModel class ، حيث قمنا بإنشاء مجموعة من labels و Input controls في form ، باستخدام asp-for tag helper مع حقول model.

للمزيد حول View يمكن الانتقال الى الرابط  Views in ASP.NET Core

يساعدنا asp-for tag helper أيضًا في إنشاء ميزة Model Binding، حتى نتمكن من الحصول على جميع قيم input controls لطريقة إنشاء action   الخاصة بي.

بعد الإضافة ستكون النتيجة : 


لحد الان عملنا action فقط لاستدعاء View. حاول تشغل التطبيق لحد الان وشوف النتيجة 

الان دور نعمل action لحفظ البيانات، تمام خلونا نعمل action جديد باسم NewStudent من نوع [HttpPost] واضف الكود التالي اليه: 


   // HTTP POST VERSION  
        [HttpPost]
        public IActionResult NewStudent(StudentsModel studentsModel)
        {      
            string connectionString = Configuration["ConnectionStrings:DefaultConnection"];
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                string sql = $"Insert Into Inventory (FullName, Birthday, Gender, Nationality, Address, UserName, Password, Email, Mobile, Note,CreatedDate)Values({studentsModel.FullName}, {studentsModel.Birthday},{studentsModel.Gender},{studentsModel.Nationality},{studentsModel.Address},{studentsModel.UserName},{studentsModel.Password},{studentsModel.Email},{studentsModel.Mobile},{studentsModel.Note},{DateTime.Now.Date})";
                using (SqlCommand command = new SqlCommand(sql, connection))
                {
                    command.CommandType = CommandType.Text;
                    connection.Open();
                    command.ExecuteNonQuery();
                    connection.Close();
                }
            }
            ViewBag.Result = "Success";        
            return View("AllStudent", studentsModel);
        }
لاحظ ان هذا action يستقبل  parameter من نوع StudentsModel حيث سيتم تعبئة حقول هذا class من View وارسالها الى هذا ال action ومن ثم حفظها بقاعدة البيانات 

شرح الكود السابق
يستخدم ASP.NET Core MVC ميزة dependency injection لتوفير خاصية من نوع IConfiguration ، والتي تسمى Configuration ، مع قيمة connection string من ملف appsettings.json.

للحصول على connection string  من ملف appsettings.json  نحتاج الى إضافة constructor  الى StudentsController التي تأخذ parameter من نوع IConfiguration. داخل هذا constructor، يتم تعيّن قيمة خاصية ل IConfiguration إلى قيمة constructor’s parameter. الكود التالي يوضح ذلك: 

public IConfiguration Configuration { get; }
        public StudentsController(IConfiguration configuration)
        {
            Configuration = configuration;
        }
أصبح الان بالإمكان الحصول على قيم Connection string  في Controller.

شرح الكود الخاص ب NewStudent action  الخاص بحفظ بيانات الطالب 
في السطر الأول، تم ارجاع سلسة الاتصال بقاعدة البيانات ConnectionStrings node  الموجودة داخل ملف appsettings.json  التي لها الاسم  DefaultConnection  وتم حفظها بمتغير باسم connectionString 
string connectionString = Configuration["ConnectionStrings:DefaultConnection"];
بعد ذلك، تم إنشاء SqlConnection class object (من namespace System.Data.SqlClient) ، عن طريق تمرير connection string إلى constructor. الكود التالي يوضح ذلك:
using (SqlConnection connection = new SqlConnection(connectionString))
{
//...
}
ثم قمنا باستخدام SqlCommand class (أيضًا من namespace System.Data.SqlClient)، من أجل إنشاء سجل طالب جديد في قاعدة البيانات.
تحتوي SqlCommand class على طريقة تسمى ExecuteNonQuery لتنفيذ SQL statement and SQL Stored procedure.
سنقوم هنا بأنشاء SQL Query لغرض إضافة طالب الى قاعدة البيانات وتخزينها في متغير من نوع string 
الكود التالي يوضح ذلك : 

string sql = $"Insert Into Students (FullName, Birthday, Gender, Nationality, Address, UserName, Password, Email, Mobile, Note, CreatedDate) Values ({studentsModel.FullName}, {studentsModel.Birthday},{studentsModel.Gender},{studentsModel.Nationality},{studentsModel.Address},{studentsModel.UserName},{studentsModel.Password},{studentsModel.Email},{studentsModel.Mobile},{studentsModel.Note},{DateTime.Now.Date})";

لاحظ ان الكود أعلاه عبارة عن امر insert  خاص ب SQL statement  حيث تم إضافة القيم من view الى هذا الامر. 
بعد ذلك، أقوم بإنشاء SqlCommand class object بتمرير 2 parameters إليه:
  • SQL Statement String
  • SQL Connection Object
الكود التالي يوضح ذلك 

using (SqlCommand command = new SqlCommand(sql, connection))
{
//...
}
ثم قمت بتعيين الخاصية CommandType إلى CommandType.Text enum والسبب اننا نسنتخدم SQL statement string وليس SQL procedure (في حال كان  SQL procedure سيكون CommandType.StoredProcedure). الكود موضح أدناه:
command.CommandType = CommandType.Text;
نظرًا لأن طريقة ExecuteNonQuery تعمل في بيئة متصلة connected environment ، لذلك يتعين علينا فتح الاتصال قبل التنفيذ وأيضًا إغلاق الاتصال بعد انتهاء التنفيذ.
الكود التالي يقوم بهذا العمل 

connection.Open();
command.ExecuteNonQuery();
connection.Close();

في اخر الكود تم استدعاء view باسم AllStudent حيث يتم عرض جميع الطلاب الموجودين في قاعدة البيانات. 
الكود كامل لملف StudentsController

  public class StudentsController : Controller
    {
        public IConfiguration Configuration { get; }
        public StudentsController(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        // HTTP GET VERSION
        public IActionResult NewStudent()
        {
            return View();
        }
        // HTTP POST VERSION  
        [HttpPost]
        public IActionResult NewStudent(StudentsModel studentsModel)
        {
            string connectionString = Configuration["ConnectionStrings:DefaultConnection"];
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                string sql = $"Insert Into Students (FullName, Birthday, Gender, Nationality, Address, UserName, Password, Email, Mobile, Note, CreatedDate) Values ({studentsModel.FullName}, {studentsModel.Birthday},{studentsModel.Gender},{studentsModel.Nationality},{studentsModel.Address},{studentsModel.UserName},{studentsModel.Password},{studentsModel.Email},{studentsModel.Mobile},{studentsModel.Note},{DateTime.Now.Date})";
                using (SqlCommand command = new SqlCommand(sql, connection))
                {
                    command.CommandType = CommandType.Text;
                    connection.Open();
                    command.ExecuteNonQuery();
                    connection.Close();
                }
            }
            ViewBag.Result = "Success";   
            return View("AllStudent", studentsModel);
        }
        public IActionResult Index()
        {
            return View();
        }
    }
تمام هيك بنكون جاهزين نشغل التطبيق ونشوف النتيجة :
شغل التطبيق وبعدها انتقل إلى
 https://localhost:44382/students/newstudent

عند النقر فوق submit يتم التحقق من بعض الحقول باستخدام Data Annotations Attributes  التي تم شرحها في اول الدرس.
ستكون النتيجة: 

أضف البيانات التي ترغب في النموذج ثم انقر فوق Submit 
اذا كان شغلك تمام وما في أخطا اكيد بكون تم اضافة حقل جديد في قاعدة البيانات ،تحقق من جدول student  في قاعدة البيانات 


 تم إضافة سجل الطالب بنجاح. 
لاحظ رقم الطالب StudentNo حيث تم إضافة الرقم 2100001  وهو عبارة عن Trigger تم اضافته للجدول مباشرة. 
لإضافة Trigger   انقر فوق إشارة + بجانب اسم الجدول ثم انقر يمين فوق Trigger ثم اختر New Trigger 



ثم أضف الكود التالي 

USE [StudentsAcademy]
GO
/****** Object:  Trigger [dbo].[GenerateStudentNumber]    Script Date: 24/09/2021 18:08:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create trigger [dbo].[GenerateStudentNumber] on [dbo].[Students] AFTER INSERT
as
begin
declare @ID int
select @ID = StudentId from inserted 
update Students set StudentNo =(select isnull(cast(max(StudentNo) as int)+1,right(DATEPART(yy,getdate()),2)+00001) from Students where 
StudentNo>= right(DATEPART(yy,getdate()),2)+00001)
where StudentId=@ID
end
في هذا الكود نقوم بإنشاء رقم مكون من 5 خانات بالإضافة الى اول رقمين من السنة الحالية. 
لإرجاع اول رقمين من السنه نستخدم الكود
 right(DATEPART(yy,getdate()),2) 
ثم نقوم بإرجاع اخر رقم تم اضافته ليتم إضافة رقم 1 في كل سجل جديد بالتسلسل. 
شكل رقم الطالب 
YY0000x
حيث ان اول رقم للطالب هو 2100001
عند تنفيذ الكود السابق سيقوم action بطلب view باسم AllStudent ولكن هنا ولأنه لم نقم بإضافة هذا View سيظهر خطأ 




سنقوم لاحقا بإضافة هذا View وعرض جميع الطلاب من قاعدة البيانات

استخدام Parameterized Command Objects
في القسم أعلاه، استخدمت hard-coded string لاستعلام SQL، كما هو موضح أدناه:

string sql = $"set dateformat dmy  Insert Into Students (FullName, Birthday, Gender, Nationality, Address, UserName, Password, Email, Mobile, Note, CreatedDate) Values ({studentsModel.FullName}, {studentsModel.Birthday},{studentsModel.Gender},{studentsModel.Nationality},{studentsModel.Address},{studentsModel.UserName},{studentsModel.Password},{studentsModel.Email},{studentsModel.Mobile},{studentsModel.Note},{DateTime.Now.Date})";

يتم في طريقة parameterized query  اضافة placeholders ل parameters مع استخدام علامة "@"، كما هو موضح أدناه.

string sql = $"set dateformat dmy  Insert Into Students (FullName, Birthday, Gender, Nationality, Address, UserName, Password, Email, Mobile, Note, CreatedDate) Values (@FullName,@Birthday,@Gender,@Nationality,@Address,@UserName,@Password,@Email,@Mobile,@Note,@Date)";

هنا تعتبر جميع التعريفات التالية parameters

@FullName, @Birthday, @Gender, @Nationality, @Address, @UserName, @Password,@Email,@Mobile, @Note, @Date   ،
وسيتعين علينا تعريفها وتزويدها بالقيم.

يعتبر Parameterized query مفيد في شيئين مهمين:
تجنب SQL injection attacks ، وهي هجوم شائع جدًا.
تنفيذ أسرع من طريقة SQL string السابقة لأنها عبارة عن pre-compiled SQL statement.. لذلك كل ما تحتاج إلى توفيره هو " parameters " (يمكن اعتبارها " variables") التي يجب إدراجها في العبارة حتى يتم تنفيذها.
لاستخدام Parameterized Command Object، يجب عليك تحديد parameters لـ SqlCommand. يتم ذلك باستخدام SqlParameter class.
يتم عرض members المهمين في فئة SqlParameter  في الجدول أدناه:



Description
Name
الحصول على أو تحديد اسم parameter.
ParameterName
الحصول على أو تحديد قيمة parameter.
Value
الحصول على أو تعيين نوع بيانات SQL Server ل parameter
SqlDbType
الحصول على أو تحديد الحد الأقصى لحجم البيانات ل parameter باستخدام bytes
Size
الحصول على أو تحديد ما إذا كانت parameter تقبل القيم null أم لا.
IsNullable
الحصول على أو تحديد ما إذا كانت parameter هي معلمة الإدخال فقط input-only أو الإخراج فقط output-only أو ثنائية الاتجاه bidirectional أو معلمة قيمة الإرجاع return value parameter.
Direction

حان الوقت الآن لتغيير الكود في "NewStudent” إلى كود باستخدام طريقة parameterized one. لذا استبدل كود NewStudent   القديم بهذا الكود المحدث الوارد أدناه:
// HTTP POST VERSION  using Parameterized Command 
        [HttpPost]
        public IActionResult NewStudent(StudentsModel studentsModel)
        {
            string connectionString = Configuration["ConnectionStrings:DefaultConnection"];
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                string sql = $"set dateformat dmy  Insert Into Students (FullName, Birthday, Gender, Nationality, Address, UserName, Password, Email, Mobile, Note, CreatedDate) Values (@FullName,@Birthday,@Gender,@Nationality,@Address,@UserName,@Password,@Email,@Mobile,@Note,@Date)";
                using (SqlCommand command = new SqlCommand(sql, connection))
                {
                    command.CommandType = CommandType.Text;
                    // adding parameters
                    SqlParameter parameter = new SqlParameter
                    {
                        ParameterName = "@FullName",
                        Value = studentsModel.FullName,
                        SqlDbType = SqlDbType.NVarChar,
                        Size = 200
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Birthday",
                        Value = studentsModel.Birthday,
                        SqlDbType = SqlDbType.DateTime
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Gender",
                        Value = studentsModel.Gender,
                        SqlDbType = SqlDbType.Int
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Nationality",
                        Value = studentsModel.Nationality,
                        SqlDbType = SqlDbType.Int
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Address",
                        Value = studentsModel.Address,
                        SqlDbType = SqlDbType.NVarChar,
                        Size=500
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@UserName",
                        Value = studentsModel.UserName,
                        SqlDbType = SqlDbType.VarChar,
                           Size = 10
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Password",
                        Value = studentsModel.Password,
                        SqlDbType = SqlDbType.VarChar,
                           Size = 200
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Email",
                        Value = studentsModel.Email,
                        SqlDbType = SqlDbType.VarChar,
                           Size = 50
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Mobile",
                        Value = studentsModel.Mobile,
                        SqlDbType = SqlDbType.VarChar,
                        Size = 10
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Note",
                        Value = studentsModel.Note,
                        SqlDbType = SqlDbType.VarChar
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Date",
                        Value = DateTime.Now,
                        SqlDbType = SqlDbType.DateTime
                    };
                    command.Parameters.Add(parameter);
                    connection.Open();
                    command.ExecuteNonQuery();
                    connection.Close();
                }
            }
            ViewBag.Result = "Success";
            return View("AllStudent");
        }
هناك تغييرات قليلة جدًا تم إجراؤها في الكود. 
أولاً: قمت بتغيير SQL query string لتحتوي على parameters  مثل:

string sql = $"set dateformat dmy  Insert Into Students (FullName, Birthday, Gender, Nationality, Address, UserName, Password, Email, Mobile, Note, CreatedDate) Values (@FullName,@Birthday,@Gender,@Nationality,@Address,@UserName,@Password,@Email,@Mobile,@Note,@Date)";

ثانيا: ثم حددت وأعطيت هذه parameters القيم التي ملأها المستخدم في النموذج الكود التالي يوضح ذلك:
SqlParameter parameter = new SqlParameter
                    {
                        ParameterName = "@FullName",
                        Value = studentsModel.FullName,
                        SqlDbType = SqlDbType.NVarChar,
                        Size = 200
                    };
                    command.Parameters.Add(parameter);

أضفت أيضًا هذه parameters إلى SqlCommand object مثل:
command.Parameters.Add(parameter);
لاحظ أيضًا بالنسبة ل @FullName parameter ، حيث قمنا بتعريف column FullName  في Students table على أنه (200)nvarchar ، لذلك قمت هنا بتعيين SqlDbType  كـ SqlDbType.NVarChar  والحجم كـ 200.
انظر بالمثل كيف عرفت @Birthday parameter:

parameter = new SqlParameter
                    {
                        ParameterName = "@Birthday",
                        Value = studentsModel.Birthday,
                        SqlDbType = SqlDbType.DateTime
                    };
                    command.Parameters.Add(parameter);
أعطيت قيمة SqlDbType  كـ SqlDbType.DateTime  (لأن Birthday column هو من النوع DateTime). لم أقم أيضًا بإضافة حقل Size   لان columns  من Money type  في SQL Server لا يحتوي على size value.
وكذلك الامر بالنسبة لباقي parameters
قم بتشغيل التطبيق الخاص بك وانتقل إلى
https://localhost:44382/students/newstudent 
ثم قم بتعبئة البيانات التي ترغب بها
تحقق الآن من Students table data في قاعدة البيانات، حيث ستجد انه تم إضافة سجل جديد في الجدول.
استخدمنا هنا Parameterized SqlCommand Object :



استخدام طريقة Stored Procedure  

(عادتا ما يختصر هذا الاسم ب  "SP") عبارة عن SQL Code Block  مخزنة في قاعدة البيانات. حيث يمكن من خلاله القيام بأي نوع من العمل مثل قراءة السجلات واضافتها وتحديثها وحذفها وما إلى ذلك من جدول قاعدة البيانات. يمكن أن تحتوي Stored Procedures أيضًا على parameters (input or output direction)).
سأقوم الآن بإنشاء stored procedure يقوم بإضافة سجلات الطلاب في Students table. سيحتوي SP هذا على 12 parameters ، حيث 11 منها تستخدم ك input direction و 1 منها يستخدم output direction.
اضافة SP
انتقل الى SQL Server Object Explorer  ثم حدد قاعدة البيانات المطلوبة، ومن ثم قم بالوصول إلى Stored Procedures node. ثم انقر يمين فوق Stored Procedures node واختر New-Stored Procedure 
لاحظ الصورة أسفل:




سيتم فتح نافذة جديدة في Visual Studio ، وتوفر لك نموذجًا لإنشاء stored procedure ، انظر الصورة أدناه:


استبدل الكود في هذه النافذة بالكود التالي:

create proc Add_New_Student(

@FullName nvarchar(200) ,
@Birthday datetime ,
@Gender int ,
@Nationality int ,
@Address nvarchar(500) ,
@UserNamen varchar(10) ,
@Password nvarchar(200) ,
@Email nvarchar(50) ,
@Mobile nvarchar(10) ,
@Note ntext,
@Result VARCHAR(50) OUTPUT
)
as 
begin 
INSERT  INTO  Students
(

FullName, 
Birthday, 
Gender, 
Nationality, 
Address, 
UserName, 
Password, 
Email, 
Mobile, 
Note, 
CreatedDate
)
values
(
@FullName ,
@Birthday ,
@Gender  ,
@Nationality  ,
@Address ,
@UserNamen  ,
@Password  ,
@Email  ,
@Mobile  ,
@Note ,
GETDATE() 

SET @Result=@@#Success@@#
end
يحتوي هذا Stored Procedure المسمى Add_New_Student على 10 input parameter هي:
@FullName nvarchar(200) ,
@Birthday datetime ,
@Gender int ,
@Nationality int ,
@Address nvarchar(500) ,
@UserNamen varchar(10) ,
@Password nvarchar(200) ,
@Email nvarchar(50) ,
@Mobile nvarchar(10) ,
@Note ntext,
يجب توفير قيم هذه parameters من التعليمات البرمجية في ADO.NET.
يحتوي procedure أيضًا على output parameter باسم Result، والذي يتم تخزين نتيجة التنفيذ اذا كانت العملية ناجحة او فاشلة. يتمثل عملها في إرجاع رسالة إلى كود ADO.NET، بحيث تدل هذه الرسالة على أنه تم إدراج السجل بنجاح او فشل في إضافة السجل.
يجب اجراء بعض التغيرات على الكود في NewStudent action في controller 
الآن استبدل Create action نوع HttpPost بالإصدار المحدث الجديد. هذا الإصدار ينفذ Add_New_Student stored procedure من كود ADO.NET.

     // HTTP POST VERSION  using SP
        [HttpPost]
        public IActionResult NewStudent(StudentsModel studentsModel)
        {
            string connectionString = Configuration["ConnectionStrings:DefaultConnection"];
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                string sql = "Add_New_Student";
                using (SqlCommand command = new SqlCommand(sql, connection))
                {
                    command.CommandType = CommandType.StoredProcedure;
                    // adding parameters
                    SqlParameter parameter = new SqlParameter
                    {
                        ParameterName = "@FullName",
                        Value = studentsModel.FullName,
                        SqlDbType = SqlDbType.NVarChar,
                        Size = 200
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Birthday",
                        Value = studentsModel.Birthday,
                        SqlDbType = SqlDbType.DateTime
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Gender",
                        Value = studentsModel.Gender,
                        SqlDbType = SqlDbType.Int
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Nationality",
                        Value = studentsModel.Nationality,
                        SqlDbType = SqlDbType.Int
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Address",
                        Value = studentsModel.Address,
                        SqlDbType = SqlDbType.NVarChar,
                        Size = 500
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@UserName",
                        Value = studentsModel.UserName,
                        SqlDbType = SqlDbType.VarChar,
                        Size = 10
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Password",
                        Value = studentsModel.Password,
                        SqlDbType = SqlDbType.VarChar,
                        Size = 200
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Email",
                        Value = studentsModel.Email,
                        SqlDbType = SqlDbType.VarChar,
                        Size = 50
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Mobile",
                        Value = studentsModel.Mobile,
                        SqlDbType = SqlDbType.VarChar,
                        Size = 10
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Note",
                        Value = studentsModel.Note,
                        SqlDbType = SqlDbType.VarChar
                    };
                    command.Parameters.Add(parameter);
                    parameter = new SqlParameter
                    {
                        ParameterName = "@Result",
                        SqlDbType = SqlDbType.VarChar,
                        Size = 50,
                        Direction = ParameterDirection.Output
                    };
                    command.Parameters.Add(parameter);
                    connection.Open();
                    command.ExecuteNonQuery();
                    string result = Convert.ToString(command.Parameters["@Result"].Value);
                    ViewBag.Result = result;
                    connection.Close();
                }
            }
            ViewBag.Result = "Success";
            return View("AllStudent");
        }

لا يوجد سوى عدد قليل من التغييرات التي تم إجراؤها من أجل تنفيذ SP. الأول هو أنه بدلاً من text query ، قمت بتعيين stored procedure’s name  ل string variable.
string sql = " Add_New_Student";
الآن سيتلقى SqlCommand object اسم SP في first parameter بدلاً من string query.
لقد قمت بتغيير خاصية CommandType إلى CommandType.StoredProcedure ، وهذا سيخبر ADO.NET أنني بحاجة إلى تنفيذ Stored Procedure هذه المرة.
command.CommandType = CommandType.StoredProcedure;
أضفت أيضًا @Result parameter جديدة وتم تعريفه من نوع direction as Output:

parameter = new SqlParameter
{
    ParameterName = "@Result",
    SqlDbType = SqlDbType.VarChar,
    Size = 50,
    Direction = ParameterDirection.Output
};
command.Parameters.Add(parameter);

ثم بعد التنفيذ ExecuteNonQuery statement  ، يمكن الحصول على القيمة التي تم إرجاعها عن طريق استخدام output parameter مثل هذا:

string result= Convert.ToString(command.Parameters["@Result"].Value);

يمكنني بسهولة استخدام return value  هذه لإخبار المستخدم outcome of this operation.
لذلك أضفت قيمة  Result@ parameter  إلى متغير ViewBag مثل ViewBag.Result = result.
وإظهار قيمة ViewBag داخل tag H2 في Create View:


<div class="container-fluid">
    <h1>Create an Inventory</h1>
    <h2 class="alert alert-danger">@ViewBag.Result</h2>
    <form method="post">
        …
    </form>
</div>