PDA

View Full Version : مبتدی: ارور در کانکشن استرینگ به روش مدل سه لایه



rezasheshbolooki
جمعه 29 خرداد 1394, 19:14 عصر
با سلام. من در حال نوشتن یک برامه به صورت مدل سه لایه هستم که در کد اتصال به دیتابیس ارور عجیبی میدهد. هرکاری کردم درسته نشد. از عوض کردن دیتابیس گرفته تا ریست کردن سیستم و حذف و دوباره درست کردن فایل اپ کانفیگ
اینم تصویر ارور: ممنون میشم اگر کار من رو راه بندازین. هرکاری کردم نشد!!!
132408

ali_md110
جمعه 29 خرداد 1394, 19:59 عصر
دوست عزیز در برنامه های چند لایه هنگام اجرای برنامه کانکشن استرینگ لایه UI مورد استفاده قرار میگیره و لایه هایی مثل DA نیاز به کانکشن استرینگ ندارند رشته اتصال خودتون به فایل کانفیگ لایه UI انتقال بدید

rezasheshbolooki
جمعه 29 خرداد 1394, 20:11 عصر
دوست عزیز در برنامه های چند لایه هنگام اجرای برنامه کانکشن استرینگ لایه UI مورد استفاده قرار میگیره و لایه هایی مثل DA نیاز به کانکشن استرینگ ندارند رشته اتصال خودتون به فایل کانفیگ لایه UI انتقال بدید

منظورت اینکه کلا این کد رو برم توی ui بذارم؟! آخه من چند جای مختلف خوندم که توی DA کانکشن ها را تعریف میکنند. من به UI رفرنس های BL و DA رو اد کردم و همچنین به DA را به رفرنس BL اد کردم اما باز هم فرقی نکرد. متوج منظور شما نشدم! با تشکر

ali_md110
جمعه 29 خرداد 1394, 22:57 عصر
لایه های DA وBLL نیازی به تعریف رشته اتصال ندارند و در واقع اطلاعات لازم را از فایل کانفیگ درون برنامه اصلی بدست میارن چون وقتی برنامه اجرا میشه همه لایه ها مانند یک اسمبلی واحد عمل کرده و به یک رشته اتصال نیاز دارن از هزجا شنیدید که درون لایه DAL تعریف میکنن یه کم از برنامه چند لایه فاصله دارن

شما یک فایل کانفیگ درون لایه UI میسازید و تنظیمات رشته اتصال رو درون اون تعریف میکنید بعد از طریق کلاس ConfigorationManager این کانگشن استرینگ رو تحویل اون لایه دلخواه مثل DAL میدیم
در این مثال فرض شده نام کانکشن استرینگ CnnString باشه


using (var cnn = new SqlConnection(ConfigurationManager.ConnectionStrin gs["CnnString"].ConnectionString))
{
}

mehdiba3
شنبه 30 خرداد 1394, 08:32 صبح
البته ببخشین تو دخالت می کنم، طبق دیزاین پترن 3 لایه در لایه DAL باید به کانکشن رو تعریف کرد و برای بهینه بودن این کار بهتره یک کلاس برای این کار درست کنین. یک نمونه کد که خودم در برنامه های تجاری ازش استفاده می کنم برات قرار می دم امیدوارم به دردت بخوره


public class DAL
{
public SqlConnection Con = new SqlConnection();
public SqlCommand Cmd;
public SqlDataAdapter Da;



public void connect()
{

//true
// Con.ConnectionString = "Data Source=.;Initial Catalog=amoozeshgah;Integrated Security=True;Asynchronous processing=true";
//ConnectionString network
// true
//Con.ConnectionString = @"Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\amoozeshgah.mdf;I ntegrated Security=True;Connect Timeout=30;User Instance=True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\amoozeshgah.mdf;I ntegrated Security=SSPI";
//true
// Con.ConnectionString = "Data Source=192.168.32.1,1433;Network Library=DBMSSOCN; Initial Catalog=amoozeshgah;User ID=User1;Password=1234";
//new
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=amoozeshgah;Integrated Security=SSPI";
try
{
Con.ConnectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=amoozeshgah;Integrated Security=True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\amoozeshgah.mdf;I ntegrated Security=True;Connect Timeout=30;User Instance=True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirector y|\amoozeshgah.mdf;User ID=sa;Password=1234";
Con.Open();
Cmd = Con.CreateCommand();
Cmd.CommandType = System.Data.CommandType.StoredProcedure;
}
catch (Exception ex) // baraye atach kardane bank
{
MessageBox.Show(ex.Message);
Con.ConnectionString = "Server = .\\SQLEXPRESS ; DataBase = master ; Integrated Security = True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\amoozeshgah.mdf;I ntegrated Security=True;Connect Timeout=30;User Instance=True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirector y|\amoozeshgah.mdf;User ID=sa;Password=1234";

Con.Open();

string str = "use master;" +
"EXECUTE sp_attach_db @dbname = N'amoozeshgah' , " +
" @filename1 = N'" + System.Environment.CurrentDirectory + "\\DataBase Amoozeshgah\\amoozeshgah.mdf'," +
"@filename2 = N'" + System.Environment.CurrentDirectory + "\\DataBase Amoozeshgah\\amoozeshgah_log.ldf'";

SqlCommand cmd = new SqlCommand(str, Con);
cmd.CommandTimeout = 100;
cmd.ExecuteNonQuery();
disconnect();

Application.Restart();




}
}
public void disconnect()
{
try
{
Con.Close();
Con.Dispose();
Cmd.Dispose();
}
catch
{

}
}

}
}





برات اناوع کانکشن ها رو هم آوردم که بتونی باشون آشنا بشی و بری نسخه های مختلف برنامت هر کدوم رو خواستی در نظر بگیری

rezasheshbolooki
شنبه 30 خرداد 1394, 12:37 عصر
البته ببخشین تو دخالت می کنم، طبق دیزاین پترن 3 لایه در لایه DAL باید به کانکشن رو تعریف کرد و برای بهینه بودن این کار بهتره یک کلاس برای این کار درست کنین. یک نمونه کد که خودم در برنامه های تجاری ازش استفاده می کنم برات قرار می دم امیدوارم به دردت بخوره


public class DAL
{
public SqlConnection Con = new SqlConnection();
public SqlCommand Cmd;
public SqlDataAdapter Da;



public void connect()
{

//true
// Con.ConnectionString = "Data Source=.;Initial Catalog=amoozeshgah;Integrated Security=True;Asynchronous processing=true";
//ConnectionString network
// true
//Con.ConnectionString = @"Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\amoozeshgah.mdf;I ntegrated Security=True;Connect Timeout=30;User Instance=True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\amoozeshgah.mdf;I ntegrated Security=SSPI";
//true
// Con.ConnectionString = "Data Source=192.168.32.1,1433;Network Library=DBMSSOCN; Initial Catalog=amoozeshgah;User ID=User1;Password=1234";
//new
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=amoozeshgah;Integrated Security=SSPI";
try
{
Con.ConnectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=amoozeshgah;Integrated Security=True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\amoozeshgah.mdf;I ntegrated Security=True;Connect Timeout=30;User Instance=True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirector y|\amoozeshgah.mdf;User ID=sa;Password=1234";
Con.Open();
Cmd = Con.CreateCommand();
Cmd.CommandType = System.Data.CommandType.StoredProcedure;
}
catch (Exception ex) // baraye atach kardane bank
{
MessageBox.Show(ex.Message);
Con.ConnectionString = "Server = .\\SQLEXPRESS ; DataBase = master ; Integrated Security = True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS; AttachDbFilename=|DataDirectory|\amoozeshgah.mdf;I ntegrated Security=True;Connect Timeout=30;User Instance=True";
// Con.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirector y|\amoozeshgah.mdf;User ID=sa;Password=1234";

Con.Open();

string str = "use master;" +
"EXECUTE sp_attach_db @dbname = N'amoozeshgah' , " +
" @filename1 = N'" + System.Environment.CurrentDirectory + "\\DataBase Amoozeshgah\\amoozeshgah.mdf'," +
"@filename2 = N'" + System.Environment.CurrentDirectory + "\\DataBase Amoozeshgah\\amoozeshgah_log.ldf'";

SqlCommand cmd = new SqlCommand(str, Con);
cmd.CommandTimeout = 100;
cmd.ExecuteNonQuery();
disconnect();

Application.Restart();




}
}
public void disconnect()
{
try
{
Con.Close();
Con.Dispose();
Cmd.Dispose();
}
catch
{

}
}

}
}





برات اناوع کانکشن ها رو هم آوردم که بتونی باشون آشنا بشی و بری نسخه های مختلف برنامت هر کدوم رو خواستی در نظر بگیری

ضمن تشکر. اما من مشکلم هنوز پا برجاست. با توجه به اینکه از sql Server استفاده میکنم نه Express اما در قسمت کانکشن هنوز ارور پا برجاست. هم از آدرس دهی initial catalog هم آدرس دهی به صورت بهینه بودن. کچلم کرده :ناراحت::ناراحت: . تیکه کد رو براتون میذارم ببینید اشکال کار کجاست؟!

namespace DA
{
public class DataAcceessLayer
{
SqlConnection con;
SqlCommand cmd;
SqlDataAdapter da;
DataTable dt;
public void dataaccesslayer()
{
con = new SqlConnection();
cmd = new SqlCommand();
da = new SqlDataAdapter();
cmd.Connection = con;
da.SelectCommand = cmd;
}

public void Connect()
{
con.ConnectionString = DA.Properties.Settings.Default.Connectionstr;
con.Open();


}



public DataTable search()
{
base.Connect();
string query = "Select * from tbl_category";
DataTable dt = base.select(query);
base.disconncet();
return dt;


به ترتیب ، اولی قطعه کدی از DA و دومی از BL

ali_md110
شنبه 30 خرداد 1394, 14:11 عصر
این DA.Properties.Settings.Default.Connectionstr همون مسیر رشته اتصال شماست ببینید آیا صحیح مقدار دهی شده یا خیر
در ضمن این خطا شاید به دلیل عدم وهله سازی SqlConnection هم باشه
شما در روال dataaccesslayer اون رو وهله سازی کردید


con = new SqlConnection();

آیا روال را فراخوانی هم کرده اید؟

rezasheshbolooki
شنبه 30 خرداد 1394, 15:03 عصر
این DA.Properties.Settings.Default.Connectionstr همون مسیر رشته اتصال شماست ببینید آیا صحیح مقدار دهی شده یا خیر
در ضمن این خطا شاید به دلیل عدم وهله سازی SqlConnection هم باشه
شما در روال dataaccesslayer اون رو وهله سازی کردید


con = new SqlConnection();

آیا روال را فراخوانی هم کرده اید؟


این هم کل کد DA :
من حتی با دیتابیس های مختلف هم امتحان کردم اما فایده ای نداشته.
مراحلی که انجام دادم:
1- اضافه کرده DA , BL
2- اضافه کردن BL , DA به رفرنس های UI
3- اضافه کردن رفرنس DA به BL
4- و بالطبع using کردن در کلاس ها.
اما اروری که میده مربوط به رفرنس ها است. حتی بیلد با موفقیت انجام میشه و به connectionstring ایراد نمیگیره اما موقع ران کردن به محضی که میخواد کانکشن رو انجام بده ارور میده.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;
using DA;


namespace DA
{
public class DataAccessLayer
{
SqlConnection con;
SqlCommand cmd;
SqlDataAdapter da;
DataTable dt;
public void dataaccesslayer()
{


con = new SqlConnection();
cmd = new SqlCommand();
da = new SqlDataAdapter();
cmd.Connection = con;
da.SelectCommand = cmd;
}
private static string connectionString = "Data Source=REZA;Initial Catalog=3LayerStoreAppDb;Integrated Security=True";
public void Connect()
{
using (SqlConnection connection = new SqlConnection(connectionString)) { }

}
public void disconnect()
{
con.Close();
con.Dispose();
}
public DataTable select(string query)
{
cmd.CommandText = query;
dt = new DataTable();
da.Fill(dt);
return dt;
}
public void docommand(string query)
{
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
}
}

ali_md110
شنبه 30 خرداد 1394, 15:28 عصر
شما مشکل وهله سازی SqlConnection دارید عزیز من
اومدید دو روال نوشتید بنام Connect و dataaccesslayer هیچ جا ازش استفاده نکردید و صدا نزدید این توابع رو درون سازنده کلاس DAL فراخوانی کنید مشکل حل میشه
در ضمن رشته اتصال یک متغیر رشته ای هست و هنگام فراخوانی و اجرای برنامه استفاده و خطایابی میشه و وقت بیلد کردن Debug نخواهدشد

rezasheshbolooki
شنبه 30 خرداد 1394, 15:39 عصر
شما مشکل وهله سازی SqlConnection دارید عزیز من
اومدید دو روال نوشتید بنام Connect و dataaccesslayer هیچ جا ازش استفاده نکردید و صدا نزدید این توابع رو درون سازنده کلاس DAL فراخوانی کنید مشکل حل میشه
در ضمن رشته اتصال یک متغیر رشته ای هست و هنگام فراخوانی و اجرای برنامه استفاده و خطایابی میشه و وقت بیلد کردن Debug نخواهدشد

خب من در BL استفاده کردم از جفتشون. هم کلاس DataAccessLayer رو مشتق گرفتم ازش و هم تابع Connect رو صدا زدم:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DA;
using System.Data;
using System.Data.SqlClient;
using BL;


namespace BL
{
public class Category:DataAccessLayer




public DataTable search()
{
base.Connect();
string query = "Select * from tbl_category";
DataTable dt = base.select(query);
base.disconnect();
return dt;


ببخشید من تازه کار هستم. جسارتا اگر توابع سازنده رو برام بذارید ممنون میشم

ali_md110
شنبه 30 خرداد 1394, 16:21 عصر
سازنده کلاس DAL اینطوری تعریف کنید


public DataAccessLayer()
{

}

مشکل اساسی با پیاده سازی برنامه چند لایه دارید
این روش شما زیادصحیح نیست برنامه های چند لایه بدین صورت هستند که یک لایه وظیفه دسترسی به منابع اطلاعاتی مثل اسکیول سرور دارد مثل DAL در این لایه شما فقط کانکشن دارید و دستورات sql و Sqlcommand به هیچ وجه به لایه blll انتقال ندید چون که لایه bll وظیفش lعمال یک سری validation هست و تعریف یک سری Temp ها برای فرمت دهی داده و در تهایت پاس دادن این داده به لایه dal هست و نباید کانکشن رو درون لایهbll l باز یا بسته کنید
برای حل مشکل شما:
ابتدا یک کلاس بسازید بنام Connection فرض کنیم پروژه شما عنوانش DataAccessLib هست



namespace DataAccessLib
{
public class Connection
{
public Connection()
{

}
public string ConectionString
{
get
{
return "رشته اتصالتون";
}
}

}

}



سپس یک کلاس به نام بسازید DAL_Person تابع درج مشخصات فقط یک پارامتر داره برای ارسال داده به اون و از نوع DataTable هست میتونید هر نوع داده ی دیگه بجاش پاس بدید


public class DAL_Person:Connection
{
public DAL_Person(): base(){}
public void Dispose()
{

if (this is IDisposable)
(this as IDisposable).Dispose();
System.GC.SuppressFinalize(this);

}
#region "Insert Update"
public int InsertPerson(DataTable tbl)
{

int intPatientID = 0;

using (SqlConnection cnn = new SqlConnection(base.ConectionString))
{
cnn.Open();

using (SqlCommand cmd = new SqlCommand("PersonInsert", cnn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@PersonID", SqlDbType.Int).Direction = ParameterDirection.Output;
cmd.Parameters.Add("@FirstName",SqlDbType.NVarChar);
cmd.Parameters.Add("@LastName", SqlDbType.NVarChar);
cmd.Parameters.Add("@MeliCode", SqlDbType.NVarChar);
for (int i = 0; i < tbl.Rows.Count; i++)
{

cmd.Parameters["@FirstName"].Value = tbl.Rows[i]["FirstName"];
cmd.Parameters["@LastName"].Value = tbl.Rows[i]["LastName"];
cmd.Parameters["@MeliCode"].Value = tbl.Rows[i]["MeliCode"];
cmd.ExecuteNonQuery();
intPatientID = Convert.ToInt32(cmd.Parameters["@PersonID"].Value);

}
try
{
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback(ex.Message);

}
finally
{
if (cnn.State == ConnectionState.Open)
{
cnn.Close();
cnn.Dispose();
}
cmd.Dispose();
}
}
}
return intPatientID;
}
#endregion

}


و لایه BLL


public class BLL_Person : IDisposable
{
#region Structor Destructor IDisposable Members سازنده و مخرب

~BLL_Person()//متد روبرو را جهت سازنده و مخرب تشکیل داده
{
Dispose();

}

private bool disposed = false;
public virtual void Dispose()
{
if (!disposed)
{
try
{
_DAL.Dispose();//کلاسمان را پاسکازی میکنیم
_DAL = null;
}
finally
{
this.disposed = true;
GC.SuppressFinalize(this);
}
}
}
//در این متد که سازنده کلاسمان میباشد متغیر بالا را نوسازی کرده

private DataAccessLib.DAL_Person _DAL;
public BLL_Person()
{
_DAL = new DataAccessLib.DAL_Person();
}

#endregion
#region "Dataset And validation"

public void validateField(ref DataTable dt)
{
if (!(System.Convert.IsDBNull(dt.Rows[0]["PersonID"])))
{
if ((int)dt.Rows[0]["PersonID"] == 0)
{
//Set it to a null value
dt.Rows[0]["PersonID"] = DBNull.Value;
}
else
{
//Trim spaces
dt.Rows[0]["PersonID"] = dt.Rows[0]["PersonID"];
}
}
else
{
dt.Rows[0]["PersonID"] = DBNull.Value;
}
}

#endregion
#region "insertUpdate"
public int InsertPerson(DataTable dt)
{
validateCredit(dt)
return _DAL.NewInsertPerson(dt);

}

#endregion

}


تمام کاری که بکنید همینه و فقط میمونه لایه نمایش که یک رفرنش میخاد از کلاس BLL و وهله سازی آن و فراخوانی متد Insert و پرکردن و ارسال یک دیتاتیبل حاوی داده بهش متد insert

rezasheshbolooki
شنبه 30 خرداد 1394, 16:45 عصر
بسیار ممنونم از شما علی جان. از روش شما رفتم و مشکل بر طرف شد اما با توجه به اینکه من دارم از ابتدا این روش رو میخونم و بر اساس فیلم های آموزشی اینکار رو میکنم در ادامه ممکنه به مشکل بخوردم و دوباره بخوام از شما کمک بگیرم. من سورس رو میذارم. دیتابیسش مهم نیست چون ارور دیتابیس نمیده. اگر امکانش هست این سورس رو نگاه کنید، بسیار بنده رو خرسند میکنید اگر کمکم کنین. با تشکر فراوانننننننن.
http://uplod.ir/zvtseaqx2wix/3LayerStore.zip.htm

ali_md110
شنبه 30 خرداد 1394, 17:07 عصر
خواهش میکنم اگر مشکل حل شد تاپیکهای اضافی رو حذف کنید سایت شلوغ نشه البته ممکنه مدیر سایت اونا رو پاک بکنه