لایه منطق تجاری (BLL یا Bussiness Logic Layer)
برنامه نویسی چند لایه قسمت سوم :
قبل از هر چیز یک پروژه دیگر به نام BLL پروژه اصلی اضافه نمایید ، روند کار دقیقا شبیه لایه قبلی است ، یک کلاس به نام Users به این پروژه اضافه نمایید .
اکنون وارد منوی Project>Addrefrence شده و از تب Project گزینه DAL را انتخاب کنید ، این کار باعث میشود مرجع لایه DAL به پروژه شما اضافه شود و شما به کدهای نوشتی شده در این لایه دسترسی پیدا کنید .
شاید در وحله اول به نظر برسد که نیازی به چنین لایه ای نیست ، در اصل این لایه چند وظیفه عمده بر عهده دارد :
واسط بین لایه DAL و UI است و باعث مرتب شدن و دسته بندی کد های می گردد
عملیات اعتبار سنجی مقادیر را بر عهده دارد تا مطمئن شویم اطلاعاتی که به دیتابیس ارسال می شوند از هر نظر بدون نقص هستند
فیلد های دیتابیس را در کلاس شبیه سازی می کند (ORMapping) تا در متدهای Select استفاده شود
در این لایه به ازای هر جدول در دیتابیس یک کلاس ایجاد خواهد شد ، تمام فیلد های جدول دیتابیس به صورت Property در کلاس پیاده سازی می شوند (به مقاله اصول شی گرایی (OOP) قسمت سوم : خواص مراجعه شود) و سپس متد های مورد نیاز ایجاد شده و متد های منتاظر در لایه DAL را فراخوانی می کنند . به عنوان مثال جدول کابران در مقاله قبل را در نظر بگیرید :
UserID : int
FirstName : nvarchar 50
LastName : nvarchar 50
EmailAddress : nvarchar 50
Username : nvarchar 20
Password : nvarchar 10
UserStatus : tinyint
اکنون ما فیلدهای این جدول را در کلاس Users در لایه BLL به صورت Property پیاده سازی می کنیم :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BLL
{
public class Users
{
public int UserID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public byte UserStatus { get; set; }
}
}
دقت نمایید که بنده Property ها را به صورت Auto Property و به صورت خلاصه تعریف کردم اگر از ورژن های پایین تر از Dotnet Framwork 3.5 استفاده می کنید لازم است که آنها را به صورت کامل تعریف کنید ، مثلا :
private int _UserID;
public int UserID
{
get
{
return _UserID;
}
set
{
_UserID = value;
}
}
اکنون که فیلد ها ایجاد شدند به سراغ پیاده سازی متد ها می رویم ، و متد AddNewUser را پیاده سازی می کنیم .
همانطور که در ابتدا گفته شد در این لایه انواع اعتبار سنجی های مورد نیاز انجام خواهد شد ، برای روشن شدن مطلب فرض کنید متد AddNewUser برای ثبت نام افراد استفاده می شود بنابراین ایمیل کاربر باید از نظر تکراری بودن چک شود ، بنابراین قبل از فراخوانی متد AddNewUser در لایه Dal باید اطلاعات به اشکال مختلف اعتبار سنجی شوند .
فرض کنید متد زیر را در لایه DAL نوشته ایم :
public int GetUserCountByEmail(string emailAddress)
{
object retVal = ExecuteScaler(System.Data.CommandType.StoredProcedure, "GetUserCountByEmailAddress", new SqlParameter[] {
new SqlParameter("@emailAddress",emailAddress)
});
if (retVal != null)
return Convert.ToInt32(retVal);
else
return 0;
}
همچنین مشابه این متد را برای چک کردن Username نیز به لایه DAL اضافه می نماییم .
اکنون در لایه BLL متد AddNewUser را به صورت زیر می نویسیم :
public static int AddNewUser(string firstname, string lastname, string emailAddress, string userName, string password, byte userStatus)
{
DAL.Users users = new DAL.Users();
int retval = 0;
if (users.GetUserCountByEmail(emailAddress) != 0)
{
retval = 1; // ایمیل قبلا ثبت شده است
}
if (retval == 0 && users.GetUserCountByUsername(userName) != 0)
{
retval = 2; // نام کاربری قبلا ثبت شده است
}
if (retval == 0)
{
users.AddNewUser(firstname, lastname, emailAddress, userName, password, 0);
}
return retval;
}
همانطور که ملاحظه می کنید در این متد ابتدا صحت ایمیل بررسی شده و اگر ایمیل قبلا ثبت شده باشد مقدار متغیر retval برابر 1 قرار میگیرد ، در مرحله دوم اگر ایمیل آزاد بود نام کابری چک می شود و در نهایت اگر هیچ مشکلی وجود نداشت کاربر ثبت می گردد .
و از این قبیل اعتبار سنجی ها که باعث می شود اطلاعات ارسالی به دیتابیس از هر نظر تمیز باشد ، البته خیلی اعمال دیگر را هم میتوان در این لایه انجام داد که به مرور زمان با آن مواجه خواهید شد .
اکنون متد GetUsers را برای دریافت لیست کلیه کاربران به صورت زیر پیاده سازی می کنیم ، دقت بفرمایید که متد مورد نیاز (GetUsers) قبلا باید در لایه DAL نوشته شده باشد :
public static List<Users> GetUsers()
{
DAL.Users users = new DAL.Users();
IDataReader dr = users.GetUsers();
List<Users> userList = new List<Users>();
while (dr.Read())
{
Users user = new Users();
user.EmailAddress = dr["EmailAddress"].ToString();
user.FirstName = dr["FirstName"].ToString();
user.LastName = dr["LastName"].ToString();
user.Password = dr["Password"].ToString();
user.UserID = Convert.ToInt32(dr["UserID"]);
user.UserName = dr["EmailAddress"].ToString();
user.UserStatus = Convert.ToByte(dr["UserStatus"]);
userList.Add(user);
}
return userList;
}
همانطور که ملاحظه می کنید ابتدا اطلاعات توسط متد GetUsers که در لایه DAL نوشته شده بود داخل یک IDataReader ریخته می شوند (دلیل انتخاب IDataReader به جای SQLDataReader حفظ استقلال این لایه از نوع بانک اطلاعاتی بوده است ، در ضمن فضا نام System.Data باید اضافه گردد ) ، در مرحله بعد یک لیست Generic از همین کلاس Users به نام userList ایجاد می گردد (متغیر های Generic به شما این امکان را می دهند که نوع داده را از نوع یک کلاس تعریف نمایید) ، سپس وارد حلقه خواندن اطلاعات می شویم ، در این حلقه یک شی جدید از همین کلاس ایجاد شده Property ها مقدار دهی می شوند و سپس این شی به لیست Generic اضافه می شوند و در نهایت این لیست از تابع Return می شوند .
با اینکار هم استقلال کلاس از نوع بانک اطلاعاتی حفظ شده و هم در لایه UI که لایه نهایی ما است هیچ نیازی به لایه DAL نخواهد بود و این یکی از اهداف لایه بندی پروژه است .
کار تقریبا تمام است ، اکنون وارد لایه UI که در مقاله قبل ایجاد کرده بودید بشوید و سپس از طریق گزینه Add Refrence و با استفاده از تب Projects لایه BLL را به این لایه اضافه نمایید .
اکنون میتوانید خیلی ساده از متدهایی که نوشتید استفاده کنید ، به عنوان مثال برای نمایش اطلاعات در یک GridView داریم :
GridView1.DataSource = BLL.Users.GetUsers();
GridView1.DataBind();
و یا برای درج یک کاربر جدید :
int retval = BLL.Users.AddNewUser("ali", "delshad", "ali@how2learnasp.net", "ali", "123");
switch (retval)
{
case 1:
Response.Write("ایمیل تکراری است");
break;
case 2:
Response.Write("نام کاربری");
break;
case 0:
Response.Write("کاربر با موفقیت ثبت شد");
break;
}
البته روشی که در بالا برای واکشی اطلاعات استفاده کردیم یک List از کلاس Users را بر میگرداند که مناسب بایند کردن در یک کنترل قابل بایند مانند Gridview یا DropDownList بود ، اگر ما بخواهیم این اطلاعات را در یک فرم نمایش دهیم دیگر نیازی به یک List از کلاس نخواهیم داشت بلکه فقط یک شی از آن کلاس مورد نیاز خواهد بود ، فرض کنید بخواهید اطلاعات یک کاربر را دریافت و آن را در یک فرم نمایش دهیم (مثلا برای ویرایش ) برای این منظور ابتدا یک متد دیگر به شکل زیر ایجاد می نماییم :
public static Users GetUserByUserID(int userId)
{
DAL.Users users = new DAL.Users();
IDataReader dr = users.GetUserByUserID(userId);
dr.Read();
Users user = new Users();
user.EmailAddress = dr["EmailAddress"].ToString();
user.FirstName = dr["FirstName"].ToString();
user.LastName = dr["LastName"].ToString();
user.Password = dr["Password"].ToString();
user.UserID = Convert.ToInt32(dr["UserID"]);
user.UserName = dr["EmailAddress"].ToString();
user.UserStatus = Convert.ToByte(dr["UserStatus"]);
return user ;
}
و برای استفاده از آن به سادگی داریم (فرض کنیم بخواهیم یک کاربر با کد 1 را درخواست کنیم ، البته شما میتوانید این کد را از QueryString یا هر جای دیگر به صورت پارامتریک دریافت نمایید ):
BLL.Users user=BLL.Users.GetUserByUserID(1);
TxtEmail.Text=user.EmailAddress;
TxtFirstName.Text=user.FirstName;
TxtLastName=user.LastName;
نکته دیگری که باید به آن توجه کنید این است که اگر رشته اتصال خود را در لایه DAL داخل وب کانفیگ قرار داده اید باید داخل لایه UI آن را دوباره بنویسید ، در پروژه بنده این رشته در AppSettings لایه DAL نوشته شده و در لایه UI در فایل Web.Config به صورت زیر Override شده است :
<appSettings>
<add key="ConStr" value="data source=.;Initial catalog=db;integrated security=true"/>
</appSettings>