السلام عليكم ان اكتب اول موضوع لي و هذا الموضوع للمحترفين فقط او شبه المحترفين اما المبتدئين فا اعتذر هذا الموضوع ليس لكم
عملت على الموضوع اكثر من 7 ساعات :( فا اي خطا تجدوه فهو هفوة و ان كانت هناك طرق افضل من التي استخدمتها فلا تبخل علينا :wink:
80 بالمية من مبرمجين يستخدمون SqlDataSoure لسهولتها و قوة ادائها مع ال DataBinding و لكن لديها العديد من المشاكل
هل مللت من حدودها و تريد التحرر من قيودها و شروطها؟
هل تود ان تعمل كلاس بحيث يعمل على السي شارب و الفيجول بيسك و ايضا مع ال ASP .net ولكن كيف ستضيفه الى ال ASP .net؟
هل مللت صعوبة التعديل على SqlDataSoure و مشاكلها؟
موضوعي هذا سوف يحررك من شروطها و ينتقل بك الى عالم جديد من الداتا سورس عالم غير منتهي و ليس لديه اي قيود او حدود -_-
لعمل كل هذا اقد لكم طريقة عمل ObjectDataSource و كيف ربطه مع الدتا كرد و الدتيل فيو
لتكملة هذا الموضوع يجب ان يكون لديك خلفية للDataBainding و كيفة انشاء كلاس :blink:
في البداية اعمل تيبل في قواعد بياناتك فيه اربع اعمدة استخدمت هنا قواعد بيانات من نوع MySQL للتغير ;) فقط يمكن العمل على اي نوع انت تفضله :happy:
CREATE TABLE arabteam.users ( userID INT(11) UNSIGNED AUTO_INCREMENT NOT NULL, Name VARCHAR(50) NOT NULL, Country VARCHAR(40), Age TINYINT(4) UNSIGNED, PRIMARY KEY (userID) );
البروسيجرات
البروسيجر الاول اسمة GetUsersDetailes يقوم هذا البروسيجر بارجاع جميع الصفوف من قواعد البيانات
DROP PROCEDURE IF EXISTS arabteam.GetUsersDetailes; CREATE PROCEDURE arabteam.`GetUsersDetailes`() BEGIN SELECT userID, Name, Country, Age FROM arabteam.users; END;
البروسيجر الثاني GetUserDetailes يقوم باعدة صف واحد من قواعد البيانات بعد ارسال ال userID له
DROP PROCEDURE IF EXISTS arabteam.GetUserDetailes; CREATE PROCEDURE arabteam.`GetUserDetailes`(in UserID INTEGER) BEGIN SELECT userID, Name, Country, Age FROM arabteam.users Where users.userID = UserID; END;
البروسيجر الثالث يقوم بضافة يوزر جديد و ارجاع ال userID
DROP PROCEDURE IF EXISTS arabteam.AddNewUser; CREATE PROCEDURE arabteam.`AddNewUser`(OUT userID INTEGER, IN Name Varchar(50), IN Country VARCHAR(40), IN age INTEGER) BEGIN INSERT INTO arabteam.users (Name, Country, Age) VALUES (Name, Country, Age); set userID := LAST_INSERT_ID(); END;
البروسيجر الرابع يقوم بتحديث الصف حسب الرقم التسلسلي
DROP PROCEDURE IF EXISTS arabteam.UpdateUser; CREATE PROCEDURE arabteam.`UpdateUser`(IN UserID INTEGER,IN name Varchar(50), IN country VARCHAR(40), IN age INTEGER) BEGIN UPDATE arabteam.users SET Users.Name = name , Users.Country = country, Users.Age = age WHERE Users.userID = UserID; END;
الخامس يقوم بخذف اليوزر
DROP PROCEDURE IF EXISTS arabteam.DeleteUser; CREATE PROCEDURE arabteam.`DeleteUser`(IN UserID INTEGER) BEGIN DELETE FROM Users WHERE ID = UserID; END;
الان نذهب الى web.config و نضيف ال ConnectionString الخاص بقوعد البيانات
<connectionStrings> <add name="MySqlConnectionString" providerName="MySql.Data.MySqlClient" connectionString="server=localhost;user id=root;password=YourPassword;persist security info=True;database=arabteam;Character Set=UTF8"/> </connectionStrings>
الان ندخل في صلب الموضوع للعمل على هذا الموضوع يجب تكون كلاسين الاول يحتوي على بروبتيز سوف نستخدمها لخزن المعلومات المستخدم
public class UserDetails
{
public UserDetails()
{
}
public UserDetails(int userID, string name, string country, int age)
{
this.userID = userID;
this.name = name;
this.country = country;
this.age = age;
}
private int userID;
public int UserID
{
get { return userID; }
set { userID = value; }
}
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private string country;
public string Country
{
get { return country; }
set { country = value; }
}
private int age;
public int Age
{
get { return age; }
set { age = value; }
}
}الكلاس الثاني يحتوي على عدد من المثيودز كل مثود له وضيفة خاصة مع قواعد البيانات لم اقوم بشرحها لانها خارج الموضوع
using System;
using System.Collections.Generic;
using System.Data;
using System.Web.Configuration;
using MySql.Data.MySqlClient;
/// <summary>
/// Summary description for UserDB
/// </summary>
public class UserDB
{
private string connectionString;
public UserDB()
{
connectionString = WebConfigurationManager.ConnectionStrings["MySqlConnectionString"].ConnectionString;
}
public UserDB(string connectionString)
{
// استخدام كونكشن خاص
this.connectionString = connectionString;
}
public int InsertUser(UserDetails user)
{
MySqlConnection con = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("AddNewUser", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new MySqlParameter("?Name", MySqlDbType.VarChar, 50));
cmd.Parameters["?Name"].Value = user.Name;
cmd.Parameters.Add(new MySqlParameter("?Country", MySqlDbType.VarChar, 40));
cmd.Parameters["?Country"].Value = user.Country;
cmd.Parameters.Add(new MySqlParameter("?age", MySqlDbType.Int16, 0));
cmd.Parameters["?age"].Value = user.Age;
cmd.Parameters.Add(new MySqlParameter("?UserID", MySqlDbType.Int32, 0));
cmd.Parameters["?UserID"].Direction = ParameterDirection.Output;
try
{
con.Open();
cmd.ExecuteNonQuery();
return (int)cmd.Parameters["?UserID"].Value;
}
catch (MySqlException)
{
throw new ApplicationException("خطا في قواعد البيانات");
}
finally
{
con.Close();
}
}
public UserDetails GetUserDetailes(int userID)
{
MySqlConnection con = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("GetUserDetailes", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new MySqlParameter("?userID", MySqlDbType.Int32, 0));
cmd.Parameters["?userID"].Value = userID;
try
{
con.Open();
MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
if (!reader.HasRows) return null;
reader.Read();
UserDetails user = new UserDetails(reader.GetInt32("userID"), reader.GetString("Name"), reader.GetString("Country"), reader.GetInt32("Age"));
reader.Close();
return user;
}
catch (MySqlException)
{
throw new ApplicationException("يوجد خطا في قواعد البيانات");
}
finally
{
con.Close();
}
}
public List<UserDetails> GetUsersDetailes()
{
MySqlConnection con = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("GetUsersDetailes", con);
cmd.CommandType = CommandType.StoredProcedure;
List<UserDetails> users = new List<UserDetails>();
try
{
con.Open();
MySqlDataReader reader = cmd.ExecuteReader();
if (!reader.HasRows)
return null;
while (reader.Read())
{
UserDetails user = new UserDetails(reader.GetInt32("userID"), reader.GetString("Name"), reader.GetString("Country"), reader.GetInt32("Age"));
users.Add(user);
}
reader.Close();
return users;
}
catch (MySqlException)
{
throw new ApplicationException("يوجد خطا في قواعد البيانات");
}
catch (Exception ex)
{
string r = ex.Message;
}
finally
{
con.Close();
}
return users;
}
public void DeleteUser(int userID)
{
MySqlConnection con = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("DeleteUser", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new MySqlParameter("?UserID", MySqlDbType.Int32, 0));
cmd.Parameters["?UserID"].Value = userID;
try
{
con.Open();
cmd.ExecuteNonQuery();
}
catch (MySqlException)
{
throw new ApplicationException("خطا في قواعد البيانات");
}
finally
{
con.Close();
}
}
public void UpdateUser(int userID, string name, string country, int age)
{
MySqlConnection con = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("UpdateUser", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new MySqlParameter("?userID", MySqlDbType.Int32, 0));
cmd.Parameters["?userID"].Value = userID;
cmd.Parameters.Add(new MySqlParameter("?name", MySqlDbType.VarChar, 50));
cmd.Parameters["?name"].Value = name;
cmd.Parameters.Add(new MySqlParameter("?country", MySqlDbType.VarChar, 40));
cmd.Parameters["?country"].Value = country;
cmd.Parameters.Add(new MySqlParameter("?age", MySqlDbType.Int32, 0));
cmd.Parameters["?age"].Value = age;
try
{
con.Open();
cmd.ExecuteNonQuery();
}
catch (MySqlException ex)
{
string ms = ex.Message;
throw new ApplicationException("خطا في قواعد البيانات");
}
finally
{
con.Close();
}
}
public void UpdateUser(UserDetails theUser)
{
MySqlConnection con = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("UpdateUser", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new MySqlParameter("?userID", MySqlDbType.Int32, 0));
cmd.Parameters["?userID"].Value = theUser.UserID;
cmd.Parameters.Add(new MySqlParameter("?name", MySqlDbType.VarChar, 50));
cmd.Parameters["?name"].Value = theUser.Name;
cmd.Parameters.Add(new MySqlParameter("?country", MySqlDbType.VarChar, 40));
cmd.Parameters["?country"].Value = theUser.Country;
cmd.Parameters.Add(new MySqlParameter("?age", MySqlDbType.Int32, 0));
cmd.Parameters["?age"].Value = theUser.Age;
try
{
con.Open();
cmd.ExecuteNonQuery();
}
catch (MySqlException ex)
{
string ms = ex.Message;
throw new ApplicationException("خطا في قواعد البيانات");
}
finally
{
con.Close();
}
}
}لحد الان لن ندخل للموضوع كل هذا هي اعدادات لبداية العمل الان لنفتح صفحة
ونضيف اليها كائن من نوع ObjectDataSource
و نكتب اسم الكلاس في TypeName و نكتب اسم الميثود في SelectMethod
<asp:ObjectDataSource ID="ODS0" runat="server" TypeName="UserDB" SelectMethod="GetUsersDetailes" />
ثم نضيف داتا كريد
<asp:GridView ID="DG1" runat="server" DataSourceID="ODS0" />
الان الناتج
لحد الان الموضوع سهل
ماذا لو اردت تمرير براميتر؟؟ الى احد الميثود الموجودة؟
لنشاهد المثيود
public UserDetails GetUserDetailes(int userID)
يجب تمرير قيمة لل userID حتى نحصل على معلومات المستخدم
في البداية دعنا نقوم نعمل List تحتوي على جميع المستخدمين و عند اختيار احد المستخديم نقوم بعرض معلوماته كاملة
لنسخدم نفس الطريقة التي استخدمناها سابقا و نقوم بربط اللست مع "ODS0"
مع اضافة الخاصتين DataTextField و DataValueField
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="ODS0" DataTextField="Name", DataValueField="UserID" />
الان لنذهب للمفيد هو كيفية اضافة باراميتر للداتا سورس اوبجكت و ربطه بالكونترل DropDownList
لنضيف ObjectDataSource ثاني
<asp:ObjectDataSource ID="ODS1" runat="server" TypeName="UserDB" SelectMethod="GetUserDetailes"> <SelectParameters> <asp:ControlParameter ControlID="ListBox1" Name="userID" PropertyName="SelectedValue" /> </SelectParameters> </asp:ObjectDataSource>
نشاهد هنا انه لقد قمت بضافة الباراميتر عن طريق ال ControlParameter
يمكن استخدام اي نوع من انواع البراميتر مثل التي في ال SqlDataSourse
كا
CookieParameter
او
QueryStringParameter
او استخدام البراميتر الاعتيادي
Parameter
كما تعرفون لانكم مبرمجون محترف او شبه محترفون ;)
الان نغير الداتا سور كرد فيو الى ال ODS1
<asp:GridView ID="DV1" runat="server" DataSourceID="ODS1" />
و لنفذ البرنامج
سنرى مشكلة هي عند تنفيذ البرنامج لاول مرة سوف يضع لنا اول اسم في القائمة ماذا لو كان المحتوى الاول هو "----الرجاء قم بختيار احد الاسماء----"؟؟
لحل هذا المشكلة يجب علينا كتابة بعد من الاكواد ولاول مرة
نذهب الى الايفينت Selecting الخاص ب ال ODS1
و نلغي العملية عند طريق تغير القيمة البولونية Cancel الى true
protected void ODS1_Selecting(object sender, ObjectDataSourceSelectingEventArgs e)
{
if (e.InputParameters["userID"] == null)
e.Cancel = true;
}الان الى تعديل البيانات و استخدام الميثود UpdateUser
لنتذكر تعريف الميثود
public void UpdateUser(int userID, string name, string country, int age)
يجب تمرير اربع براميترات الى الميثود لاكمال عملية الادخال
في البداية عدنا نعرف الميثود في الاوبجكت ObjectDataSource
باضافة البروبرتي UpdateMethod ولا تنسى تفعيل خاصية التعديل في الGridView
<asp:ObjectDataSource ID="ODS1" runat="server" TypeName="UserDB" SelectMethod="GetUserDetailes" oninserting="ODS1_Inserting" UpdateMethod="UpdateUser"> <SelectParameters> <asp:ControlParameter ControlID="ListBox1" Name="userID" PropertyName="SelectedValue" /> </SelectParameters> </asp:ObjectDataSource>
لقد مررنا اسم الميثود الخاص بالتحديث
"UpdateMethod="UpdateUser
الفيو كرد
<asp:GridView ID="DV1" runat="server" DataSourceID="ODS1" > <Columns> <asp:CommandField ShowEditButton="True" /> </Columns> </asp:GridView>
الان نفذ البرنامج
لم انسى البراميترز و لكني لم اقم بضافتها لان الاوبجكت هو الذي قام بذالك عني
عندما يحصل الاوبجكت على المعلومات يقوم بضافة البراميترز حسب البروتبرتيز الاول اذن هو من قام بضافة
userID, Name , Country , Age
الان يخطر في بالك سؤال كيف استطاع التميز بينهما هناك نقطتان يعتمد عليها الاوبجكت
الاول عدد البراميترز المرسلة الى الميثود
الثانية يقوم بالتاكد من اسماء المتغيرات و مطابقتها اي بمعنى يجب عليك وضع نفس الاسماء الموجودة داخل الداتا سورس بمعنى نفس الاسماء التي يعديها الميثود الموجود داخل ال SelectMethod
و هي في موضوعنا هذا البروبرتيز الموجود في UserDetailes
ولكن لانك مبرمج محترف سوف تفضل عمل الميثود بهذه الصورة و هي الصورة الاكثر شيوعاً بين المبرمجين
public void UpdateUser(UserDetails theUser)
{
MySqlConnection con = new MySqlConnection(connectionString);
MySqlCommand cmd = new MySqlCommand("UpdateUser", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new MySqlParameter("?userID", MySqlDbType.Int32, 0));
cmd.Parameters["?userID"].Value = theUser.UserID;
cmd.Parameters.Add(new MySqlParameter("?name", MySqlDbType.VarChar, 50));
cmd.Parameters["?name"].Value = theUser.Name;
cmd.Parameters.Add(new MySqlParameter("?country", MySqlDbType.VarChar, 40));
cmd.Parameters["?country"].Value = theUser.Country;
cmd.Parameters.Add(new MySqlParameter("?age", MySqlDbType.Int32, 0));
cmd.Parameters["?age"].Value = theUser.Age;
try
{
con.Open();
cmd.ExecuteNonQuery();
}
catch (MySqlException ex)
{
string ms = ex.Message;
throw new ApplicationException("خطا في قواعد البيانات");
}
finally
{
con.Close();
}
}انظر لعد تم استبدال البراميترز الاربعة بي براميتر واحد
اننا نواجه مشكلة :(( هل يوجد حل؟؟؟
بالطبع مايكروسوفت وضعت لك الحل و هي بتعريف ال UserDetailes
داخل الاوبجكت و بسطر واحد فقط ;)
اضف اسم الكلاس في البروبرتيز DataObjectTypeName="UserDetails"
<asp:ObjectDataSource ID="ODS1" runat="server" TypeName="UserDB" SelectMethod="GetUserDetailes" UpdateMethod="UpdateUser" onselecting="ODS1_Selecting" DataObjectTypeName="UserDetails"> <SelectParameters> <asp:ControlParameter ControlID="ListBox1" Name="userID" PropertyName="SelectedValue" /> </SelectParameters> </asp:ObjectDataSource>
و الان جرب الكود لم يتغير شي يمنك الان حذف المثيود الاول لن تحتاج
الان الى المرحلة الاخيرة لنتذكر معا الميثود الخاص باضافة مستخدم جديد
public int InsertUser(UserDetails user)
نلاحظ هنا ان الميثود يقوم بارجاع ID المستخدم الجديد هل من الممكن الحصول على هذا القيمة؟؟؟ :wacko:
نعم من الممكن هذا
قم با ضافة Label لمساعدتنا على التاكد من ان الايدي صحيح
<asp:Label ID="Label1" runat="server" EnableViewState="false" />
و اقوم باضافة DetailsView مع تفعيل خاصية الاضافة لها
<asp:DetailsView ID="DV0" runat="server" DataSourceID="ODS1" AllowPaging="True"> <Fields> <asp:CommandField ShowEditButton="True" ShowInsertButton="True" /> </Fields> </asp:DetailsView>
الان يجب اضافة باراميتر الى الاوبجكت البراميتر حاله حال اي براميتر اخر و اضافة الايفنت OnInserted سوف نستخدمه لاحقاً
و اضافة ال InsertMethod
<asp:ObjectDataSource ID="ODS1" runat="server" TypeName="UserDB" SelectMethod="GetUserDetailes" UpdateMethod="UpdateUser" InsertMethod="InsertUser" onselecting="ODS1_Selecting" DataObjectTypeName="UserDetails" oninserted="ODS1_Inserted"> <SelectParameters> <asp:ControlParameter ControlID="ListBox1" Name="userID" PropertyName="SelectedValue" /> </SelectParameters> <InsertParameters> <asp:Parameter Direction="Output" Name="userID" Type="Int32" /> </InsertParameters> </asp:ObjectDataSource>
الان مين اين سوف نحصل على القيمة المرجوعة؟؟؟
بعد الانتهاء العملية سوف يطلق الObjectDataSource الايفنت oninserted
و تحت الاركمنت لهذا الايفنت يوجد الخاصة ReturnValue التي تحمل قيمة البرامتير الخارج ;)
protected void ODS1_Inserted(object sender, ObjectDataSourceStatusEventArgs e)
{
Label1.Text = "تم اضافة المستخدم :" + e.ReturnValue.ToString();
}اتمنى ان يكون الموضوع مفيد لكم و اي سؤال او استفسار انا حاضر -_-
ملف السورس كامل في المرفق الاخير :wub: