1398-03-15 21:34 راهنمایی در ذخیره تصاویر در دیتابیس و ایجاد دیتاگرید ویوو در فرم frmEditContact
booysusa

 
درود بر شما مهندس حاجی شریفی گرامی
سپاس بابت راهنمایی های قبل، واقعا زحمتتون دادم

یک برنامه ساده نوشتم به قصد آموزش و الگو برداری در برنامه اصلی: این برنامه اطلاعات اولیه مانند (نام، نام خانوادگی، جنسیت، کدملی و تاریخ تولد) رو از مشتری میگیره و در دیتابیس ذخیره می کنه
بعد از زدن دکمه ثبت ، اطلاعات درون دیتابیس ذخیره می شوند و درون دیتاگرید ویو نمایش داده می شوند

مرحله بعد برای تکمیل اطلاعات (پیرو آموزش قبلی شما) شروع به تکمیل ثبت نام می کنم، برای اینکار بر روی دکمه تکمیل اطلاعات کلیک میکنم و همه اطلاعات درون فرم frmEditContact لود می کنم و موارد اضافه مانند اطلاعات کارت ملی، تصاویر، حساب مشتری را تکمیل می کنم

الان مشکل من در قسمت درج اطلاعات حساب مشتری و درج تصاویر مدارک مشتری هست
میخوام تصاویر مشتری که ممکن است شامل اسکن کارت ملی پایان خدمت مدکر تحصیلی نتیجه آزمایشات و تصویر دفترچه بیمه مشتری باشد را درون دیتابیس ذخیره کنم و نام تصاویر و حجم آنها و تصویر کوچکی از آن در دیتاگرید ویو در فرم frmEditContact نمایش داده شود

و همچنین درون بخش حساب در فرم frmEditContact میخوام برای مشتری که میاد و ممکن هست هزینه را قسطی یا بصورت قرضی حساب کند یکسری اطلاعات وارد کنم و درون یک دیتا گرید ویو در بخش حساب درون فرم frmEditContact نمایش بدهد

ممنون میشم دراینباره کمکم کنید، در اینترنت کلی گشتم و چیزهایی فرا گرفتم ولی آموزش مناسبی که به نوع کدنویسی من بخورد پیدا نکردم، ممنون میشم بر اساس نوع کدنویسی من این پروژه را کمک من تکمیل کنید، امیدوارم بتونید دیتابیس رو اتچ کنید ، من با Sql 2017 نوشتمش (لطفا کدنویسی تغییر نکند زیرا من دانشم یک دهم شما هم نیست و با کوچکترین تغییر هنگ می کنم)

نکته: یادم هست یکباری گفتید یک کتابخانه قبلا استفاده کردید برای ذخیره تصاویر با آدرس، ولی نمیدانم یک پوشه کنار برنامه بود و یا.... اگر امکانش هست یک راه استاندارد و به روش کدنویسی من باشد (خیلی گیر این مورد هستم)


اگر کار دراید و سرتان شلوغ هست درک می کنم و مشکلی نیست صبر میکنم چون خیلی گشتم و مطلب خوندم ولی از حصول نتیجه خسته شدم
بازم سپاسگزارم از شما بابت وقتی که میزارید برای راهنمایی


مشخصات برنامه
ویژوال استودیو 2015
سی شارپ
دیتابیس sql2017

لینک دانلود برنامه
1398-03-17 11:06
حاجی شریفی
مؤسس سایت
 
نقل قول نوشته شده توسط: booysusa
... میخوام تصاویر مشتری که ممکن است شامل اسکن کارت ملی پایان خدمت مدکر تحصیلی نتیجه آزمایشات و تصویر دفترچه بیمه مشتری باشد را درون دیتابیس ذخیره کنم و نام تصاویر و حجم آنها و تصویر کوچکی از آن در دیتاگرید ویو در فرم frmEditContact نمایش داده شود ...

بالاخره تصمیم تان بر ذخیره تصاویر در دیتابیس است، یا ذخیره در هارد؟!

نقل قول نوشته شده توسط: booysusa
... لطفا کدنویسی تغییر نکند ...

یعنی EntityFramework هم استفاده نکنم؟ اینکه کدنویسی با اعمال شاقه میشود
( کدهای دفعه قبل که برایتان فرستادم که خیلی کمتر بود )

بدون EF
public List<Contact> Read() // خواندن جدوال از دیتابیس
{
string command = "Select * from ContactView";
var db = new DataAccess.DatabaseManager();
var result = db.GetData(command);

List<Contact> lstResult = new List<Contact>();
foreach (DataRow r in result.Rows)
{
Contact contact = new Contact();
//// اطلاعات شناسنامه
contact.ID = Convert.ToInt64(r["ID"]);
contact.Name = r["Name"].ToString();
contact.NameKhanevadegi = r["NameKhanevadegi"].ToString();
contact.Jensiat = Convert.ToBoolean(r["Jensiat"]); // اینجا جنسیت را با رادیو باتن مشخص میکنم
contact.ShomarehMeli = r["ShomarehMeli"].ToString();
contact.TarikhTavalod = Convert.ToDateTime(r["TarikhTavalod"]);

//اطلاعات کارت ملی
contact.idk = Convert.ToInt64(r["idk"]);
contact.SerialKartMeli_KartMeli = r["SerialKartMeli_KartMeli"].ToString();
contact.NoeKartMeli = (bool)r["NoeKartMeli"];

// حساب
contact.idh = Convert.ToInt64(r["idh"]);
contact.Dasteh_Hesab = r["Dasteh_Hesab"].ToString();
contact.Mozo_Hesab = r["Mozo_Hesab"].ToString();
contact.Baha_Hesab = r["Baha_Hesab"].ToString();
//contact.Tarikh_Hesab = Convert.ToDateTime(r["Tarikh_Hesab"]);
contact.Tozihat_Hesab = r["Tozihat_Hesab"].ToString();
contact.ShomarehMeli = r["ShomarehMeli"].ToString();

// عکس
contact.idi = Convert.ToInt64(r["idi"]);
contact.Name_Image = r["Name_Image"].ToString();
contact.Tasvir_Image = r["Tasvir_Image"].ToString();
contact.Tozihat_Image = r["Tozihat_Image"].ToString();

lstResult.Add(contact);
}
return lstResult;
}



با EF
public List<Contact> Read() // خواندن جدوال از دیتابیس
{
using (var db = new DataAccess.DatabaseContext())
return db.ContactView.ToList();
}
1398-03-17 14:47
booysusa

 
نقل قول
بالاخره تصمیم تان بر ذخیره تصاویر در دیتابیس است، یا ذخیره در هارد؟!

مانده ام
برخی میگوید ذخیره در دیتابیس حجم دیتابیس بالا می برد و باعث کندی برنامه میشود، برخی میگویند ذخیره در دیتابیس امنیت اطلاعات را بالا می برد
برنامه من که میدانید برای چه هست، شاید بیش از 30 گیگ عکس درونش ذخیره کنم، حال تکلیفم چیست ؟

نقل قول
یعنی EntityFramework هم استفاده نکنم؟ اینکه کدنویسی با اعمال شاقه میشود


( کدهای دفعه قبل که برایتان فرستادم که خیلی کمتر بود )

بله سپاسگزارم ولی همان کدها باعث افت فشار من شد

چنان حرفه ای کار کرده بودید(در چشم من اینگونه آمد)
من فعلا به همین روش کد میزنم تا در آینده ای نزدیک (پس از تکمیل این برنامه) دانشم را در مورد EntityFramework را گسترش دهم

نقل قول
بدون EF
public List<Contact> Read() // خواندن جدوال از دیتابیس
{
string command = "Select * from ContactView";
var db = new DataAccess.DatabaseManager();
var result = db.GetData(command);

List<Contact> lstResult = new List<Contact>();
foreach (DataRow r in result.Rows)
{
Contact contact = new Contact();
//// اطلاعات شناسنامه
contact.ID = Convert.ToInt64(r["ID"]);
contact.Name = r["Name"].ToString();
contact.NameKhanevadegi = r["NameKhanevadegi"].ToString();
contact.Jensiat = Convert.ToBoolean(r["Jensiat"]); // اینجا جنسیت را با رادیو باتن مشخص میکنم
contact.ShomarehMeli = r["ShomarehMeli"].ToString();
contact.TarikhTavalod = Convert.ToDateTime(r["TarikhTavalod"]);

//اطلاعات کارت ملی
contact.idk = Convert.ToInt64(r["idk"]);
contact.SerialKartMeli_KartMeli = r["SerialKartMeli_KartMeli"].ToString();
contact.NoeKartMeli = (bool)r["NoeKartMeli"];

// حساب
contact.idh = Convert.ToInt64(r["idh"]);
contact.Dasteh_Hesab = r["Dasteh_Hesab"].ToString();
contact.Mozo_Hesab = r["Mozo_Hesab"].ToString();
contact.Baha_Hesab = r["Baha_Hesab"].ToString();
//contact.Tarikh_Hesab = Convert.ToDateTime(r["Tarikh_Hesab"]);
contact.Tozihat_Hesab = r["Tozihat_Hesab"].ToString();
contact.ShomarehMeli = r["ShomarehMeli"].ToString();

// عکس
contact.idi = Convert.ToInt64(r["idi"]);
contact.Name_Image = r["Name_Image"].ToString();
contact.Tasvir_Image = r["Tasvir_Image"].ToString();
contact.Tozihat_Image = r["Tozihat_Image"].ToString();

lstResult.Add(contact);
}
return lstResult;
}

این کدها همان کدها من در برنامه هستند!!!

مهندس شریفی یه مشکلی دارند برای همین لینک دانلود فرستادم
1398-03-22 22:36
booysusa

 
با درود
اون مشکلات رو برطرف کردم
الان میخوام تاریخ تولد بصورت null به دیتابیس ارسال بشود
داده تاریخ تولد در دیتابیس از نوع Date هست
اینم کدش هست که نوشتم براش
var Tarikh_HesabParameter = new SqlParameter("@Tarikh_Hesab", Tarikh_Hesab == null ? null : Convert.ToDateTime(Tarikh_Hesab));



ولی خطا میده، مهندس میشه این کدرو یه نگاه بهش بندازید

اینم تصویری از کل کد هست
1398-03-23 10:25
حاجی شریفی
مؤسس سایت
 
سلام
میبخشید فرصت نکردم روی پروژه ای که فرستادید کار کنم، احتمالا جمعه عصر یا شب شاید فرصت کنم ...

نقل قول نوشته شده توسط: booysusa
این کدها همان کدها من در برنامه هستند

بله، خواستم تفاوت "بدون EF" و "با EF" را نشان دهم...
مجدد دقت کنید کد اول ، کد شما "بدون EF" است، ببینید چند خط شده و چقدر پر از نکاتی است که اگر رعایت نشود، برنامه به خطا خواهد خورد.
کد دوم کد "با EF" است که بسیار کوتاه تر و ساده تر و قابل فهم تر است.

نقل قول نوشته شده توسط: booysusa
اون مشکلات رو برطرف کردم

خیلی خوب است که خودتان حلش کردید.
یعنی دیگر مشکلی با ذخیره فایل (یا در دیتابیس یا در هارد و...) ندارید؟ یعنی فعلا کاری نیاز نیست من انجام دهم؟

نقل قول نوشته شده توسط: booysusa
داده تاریخ تولد در دیتابیس از نوع Date هست، اینم کدش هست که نوشتم براش

اول اگر میخواهید Tarikh_Hesab بتواند خالی/Null هم قبول کند و نگاه دارد، باید آن را از جنس DateTime? تعریف کنید.

...
public DateTime? Tarikh_Hesab { get ; set ; }
...
اگر از آن کنترلر استفاده میکنید، خودش تبدیل تاریخ انجام میدهد و بدین شکل هم میتوانید فیلد را پر کنید
Contact.Tarikh_Hesab = mtxTarikh_Hesab.IsNull ? default (DateTime?) : mtxTarikh_Hesab.Value;
یا
Contact.Tarikh_Hesab = mtxTarikh_Hesab.IsNull ? (DateTime?)null : mtxTarikh_Hesab.Value;
...
و در کد ارسال به دیتابیس هم باید شبیه این عمل کنید
var Tarikh_HesabParameter = new SqlParameter("@Tarikh_Hesab", Tarikh_Hesab.HasValue ? (object )Tarikh_Hesab.Value : DBNull.Value);
...

فیلد دیتابیس هم که باید Nullable باشد.
اگر هر سه قسمت کد را دقیق مانند همین بالا که برایتان نوشتم انجام دهید، مشکلی در Null تاریخ نخواهید داشت.
موفق باشید.
1398-03-23 23:02
booysusa

 
سپاسگزارم مهندس
دیروز (با کلی تحقیق و آزمون خطا) راه حل هارو یه جورایی به دست اوردم و این قسمت برنامم بسته شد خداروشکر
ولی راه های شما بسیار بسیار منطقی هستند

1. ویرایش سطر
الان یه مشکلی که دارم (تمومی ندارن) اینه که میخوام عکس یک سطر را در گرید ویوو ویرایش کنم، به صورت رشته باشه راحت هست ویرایشش، ولی نمی دونم تصویر رو چطوری پاس بدم برای ویرایش
این کد ساده رو بروی ویرایش رشته استفاده می کنم و درست کار میکنه
txtName_Image.Text = dataGridView1.CurrentRow.Cells["ClmnName_Image"].Value.ToString() ;


ولی برای تصویر نمیدونم چطوری بنویسمش (اینو نوشتم ولی خب کار نمی کنه ) میدونم کد پائین اشتباه هست، ولی نمیدونم چطوری کدش رو بنویسم که این سطر رو پاس بده به ContactPictureBox که یه PictureBox هست
ContactPictureBox.Image = dataGridView1.CurrentRow.Cells["ClmnTasvir_Image"].Value.ToString() ;


2. کمبوباکس
و همچنین میخوام دسته رو که انتخاب می کنم مثلا طرف بدهکار هست یا بستانکار، میخوام در دیتابیس بجای نوشتن بستانکار و بدهکار از عددهای 1 و یا 2 استفاده کنم
کد رو نوشتم ولی نمی دونم چطوری موقع لود فرم توی گرید ویو بجای 2 که در دیتابیس ذخیره شده مثلا نوشته بشه بدهکار و اگر 1 بود نوشته بشه بستانکار

این کد برای ذخیره در دیتابیس هست
if (cmbDasteh_Hesab.SelectedIndex == 0)
{
//کد جستجو بر اساس نام
Contact.Dasteh_Hesab = "1";
}
else if (cmbDasteh_Hesab.SelectedIndex == 1)
{
//کد جستجو بر اساس نام خانوادگی
Contact.Dasteh_Hesab = "2";
}


این هم کد خواندن اطلاعات هست
public List<Contact> ReadHesab(long contactId) // خواندن جدول حساب از دیتابیس
{
string command = $"Select * from Hesab WHERE Contact_ID = {contactId}" ;
var db = new DataAccess.DatabaseManager() ;
var result = db.GetData(command);
List<Contact> lstResult = new List<Contact>() ;
foreach (DataRow r in result.Rows)
{
Contact contact = new Contact() ;
// حساب
contact.idh = Convert.ToInt64(r["idh"]) ;
contact.Dasteh_Hesab = r["Dasteh_Hesab"].ToString() ; // اینو میخوام وقتی لود بشه 1 یا 2 لود نشه و بدهکار یا بستانکار نوشته بشه
contact.Mozo_Hesab = r["Mozo_Hesab"].ToString() ;
contact.Baha_Hesab = r["Baha_Hesab"].ToString() ;
contact.Tarikh_Hesab = r["Tarikh_Hesab"].ToString() ;
contact.Tozihat_Hesab = r["Tozihat_Hesab"].ToString() ;
lstResult.Add(contact) ;
}
return lstResult;
}
1398-03-24 20:13
حاجی شریفی
مؤسس سایت
 
سلام
دسترسی به مقادیر سطرها به وسیله Cells[***].Value اصلا روش خوبی نیست ولی بگذریم و باشد برای بعد که خواستید کدتان ارتقا دهید و بهترش کنید ...

نقل قول نوشته شده توسط: booysusa
ولی برای تصویر نمیدونم چطوری بنویسمش ... اینو نوشتم ولی ...

اگر مجبور باشم با روش خودتان پاسخ بدهم، کدی شبیه این احتمالا کارتان را راه می اندازد:
ContactPictureBox.Image = dataGridView1.CurrentRow.Cells["ClmnTasvir_Image"].Value as System.Drawing.Image ;

(* به شرطی که فیلد اصلی که bind کرده اید از نوع Image بوده باشد *)

نقل قول نوشته شده توسط: booysusa
و همچنین میخوام دسته رو که انتخاب می کنم مثلا طرف بدهکار هست یا بستانکار، میخوام در دیتابیس بجای نوشتن بستانکار و بدهکار از عددهای 1 و یا 2 استفاده کنم

خود DataGridView کنترلر ComboBox دارد و باور کنید استفاده از آن ساده تر است، امیدوارم از روش های دیگر استفاده نکنید.
کافی است به خصیصه Columns در DataGridView بروید و برای ستون مورد نظرتان از DataGridViewComboBoxColumn استفاده کنید.

یک برنامه کوچک نمادین برایتان نوشتم که در این برنامه بطور نمادین و خیلی ساده خواسته ایم یک جدول شیفت بندی کاری را بین افراد برقرار کنیم.
سطرها ساده هستند، نام فرد و روز-هفته که نوبت اوست ولی بجای روز-هفته عدد را میخواهیم ذخیره کنیم و در DataGridView متن را نشان دهیم.
public class  DatabaseRow
{
public string People { get ; set ; }
public int DayOfWeek { get ; set ; }
}


خیلی ساده ، برای روز-هفته از DataGridViewComboBoxColumn استفاده کرده ایم و فهرست اعداد و متن ها را چنین به آن خورانده ایم:
var  combo_list = new  ComboBoxColumn[]
{
new ComboBoxColumn() { ID = 0, Text = "Saturday" },
new ComboBoxColumn() { ID = 1, Text = "Sunday" },
new ComboBoxColumn() { ID = 2, Text = "Monday" },
new ComboBoxColumn() { ID = 3, Text = "Tuesday" },
new ComboBoxColumn() { ID = 4, Text = "Wednesday" },
new ComboBoxColumn() { ID = 5, Text = "Thursday" },
new ComboBoxColumn() { ID = 6, Text = "Friday" }
};
this .colDayOfWeek.DataSource = combo_list ;
this .colDayOfWeek.ValueMember = "ID" ;
this .colDayOfWeek.DisplayMember = "Text" ;

حتی ساده تر از این و با کدنویسی کمتر هم میشد ولی هرچه من کد را کمتر میکنم، شما بیشتر میگویید سخت شده


واین هم نتیجه نهایی:
DGVComboBoxColumn.zip 5KB

کافی است همین را در برنامه تان انجام دهید.
موفق باشید.
1398-03-24 22:47
booysusa

 
درود بر شما مهندس شریفی گرامی
نقل قول
دسترسی به مقادیر سطرها به وسیله Cells[***].Value اصلا روش خوبی نیست ولی بگذریم و باشد برای بعد که خواستید کدتان ارتقا دهید و بهترش کنید ...

بله معمولا اینچنین دسترسی نمیدم ولی فعلا این کارو کردم، در آپدیت های بعدی کد رو اصلاح و ارتقا میدم

نقل قول
اگر مجبور باشم با روش خودتان پاسخ بدهم، کدی شبیه این احتمالا کارتان را راه می اندازد:
ContactPictureBox.Image = dataGridView1.CurrentRow.Cells["ClmnTasvir_Image"].Value as System.Drawing.Image ;

بله این کد رو خواستم، واقعا سپاسگزارم درست هست

نقل قول
خود DataGridView کنترلر ComboBox دارد و باور کنید استفاده از آن ساده تر است، امیدوارم از روش های دیگر استفاده نکنید.

شما درست میگید ولی یادمه قبلا یه روشی استفاده میکردمکه اینجوری به دیتابیس پاس می دادم

// مثلا
// اگر 0 بود "بدهکار"
// اگر 1 بود "بستانکار"

if (cmbDasteh_Hesab.SelectedIndex == 0)
{
Contact.Dasteh_Hesab = "1";
}
else if (cmbDasteh_Hesab.SelectedIndex == 1)
{
Contact.Dasteh_Hesab = "2";
}


بعد با یه همچین کدی اون 1 رو موقع فراخوانی در دیتابیس تبدیل به بستانکار و بدهکار می کرد
if (cmbDasteh_Hesab.SelectIndex)
{
Contact.Dasteh_Hesab = "بستانکار";
}
else if (cmbDasteh_Hesab.SelectIndex)
{
Contact.Dasteh_Hesab = "بدهکار" ;
}


البته خوب میدانم کد بالا سراسر اشتباه هست
1398-03-24 22:48
booysusa

 
ببخشید مهندس چرا من هروقت کد سی شارپ می نویسم خراب میشه فرم؟
1398-03-25 22:43
حاجی شریفی
مؤسس سایت
 
سلام
نقل قول نوشته شده توسط: booysusa
قبلا یه روشی استفاده میکردمکه اینجوری به دیتابیس پاس می دادم

احتمالا از این روش برای نمایش و ویرایش یک سطر تک استفاده میکردید.

نقل قول نوشته شده توسط: booysusa
چرا من هروقت کد سی شارپ می نویسم خراب میشه فرم؟

منظورتان در همین سایت است؟
اینجا از فرمتی به نام BBCode استفاده میکنیم.
این فرمت در تالارهای گفتگو بسیار رایج است.
کنترلری که برای ویرایش استفاده کرده ام در تبدیل کد Paste شده به BBCode مشکل دارد. البته این مشکل در سایر ویرایشگرهای BBCode هم تا حدودی وجود دارد.
(شاید باید استفاده از ویرایشگرهای دیگر را هم امتحان کنم)

آخرین دکمه کنترلر به حالت نمایشی و کدمنبع BBCode سوییچ میکند.


یعنی با زدن این دکمه میتوانید کد BBCode را مستقیم و بیواسطه وارد کنید.
این فرمت ساختاری تگ بندی شده دارد که استاندارد و مشخص است.
بطور نمونه برای درج کد میتوانید از تگ [CODE] استفاده کنید.
یا برای نقل قول یک مطلب میتوانید از تگ [QUOTE] استفاده کنید.
تگ های IMG, CENTER, LTR, I, B, U, URL, SIZE و... هم رایج هستند.
با شناخت این فرمت و ورود مستقیم BBCode دلخواه میتوانید، قالب متن زیبا و مطلوب خود را ایجاد کنید.