PDA

View Full Version : سوال: خطای کانکشن و select در تکنولوژی Entity Framework به صورت چند لایه



ghasem110deh
یک شنبه 07 تیر 1394, 18:55 عصر
سلام
دوستان خطای زیر برای چیه ؟ (عکس ضمیمه)
با درج مشکلی نداره !!!

RmeXXXXXXXXX
یک شنبه 07 تیر 1394, 23:12 عصر
میگه: الگوی کوئری رعایت نشده. آیا کوئری شما هیچ شرطی نیاز ندارد؟ خوب از متد ToList یا ToListAsync استفاده نمائید.

var view= from tb in Con.Ostad
where tb.Id==10
select tb;

ghasem110deh
یک شنبه 07 تیر 1394, 23:21 عصر
ممنون ولی این نیست همین کد توی فرم کار میکنه ...
اینجا (سه لایه) توی دال نمیدونم چرا ایطوری شده !!؟

void Show_Student() // {
// var view = from tb in con.Students
// select new { tb.S_Id, tb.Name, tb.Family, tb.Code_Melli, tb.Mark, tb.O_Id };

کانکشن که هست .... نمیدونم چشه ؟

RmeXXXXXXXXX
یک شنبه 07 تیر 1394, 23:23 عصر
using System.Linq;

ghasem110deh
یک شنبه 07 تیر 1394, 23:54 عصر
:اشتباه:
میدونی چند ساعت سر کارم ....

-----------------------------------

پس چرا به اولی (که استفاده شده) گیر نداد ؟

ghasem110deh
دوشنبه 08 تیر 1394, 02:12 صبح
دیگه تاپیک جدید نزدم ...
حالا تو نمایش توی گرید ویو به مشکل خوردم (ما مشکل داریم یا EF) :گیج:

public DataTable Ostad_Select() {
DataTable dt = new DataTable();
var view = from tb in Con.Ostad
select new { tb.O_Id, tb.Dars_Id, tb.Name, tb.Family };
//var view_query = from p1 in Con.Ostad
//join p2 in Con.Dars on p1.Dars_Id equals p2.D_Id into list1
//from l1 in list1.DefaultIfEmpty()
//select new { p1.O_Id, p1.Name, p1.Family, p1.Dars };
return dt;
}

توی فرم هم اینجوری صدا کردم :

DataTable dt = new Ostad_Bll().Select();
dataGridView1.DataSource = dt.Select().ToList();

اینم خروجی : (عکس ضمیمه)

Mahmoud.Afrad
دوشنبه 08 تیر 1394, 03:40 صبح
چرا دیتاتیبل استفاده کردی در صورتی که به نظر من وقتی داری از EF استفاده میکنی کلا بی خیال دیتاتیبل و دیتاست شو چون تمام داده ها به صورت شئ گرا در دسترس هستند. در ضمن دیتاتیبل خالیه.
کدت رو به اینصورت بنویس.

public IEnumerable<Ostad> Ostad_Select()
{
var view = from tb in Con.Ostad
select tb;
return view;
}


حالا اگر متد Ostad_Select در bll در متد Select فراخوانی بشه به اینصورت استفاده کن

IEnumerable<Ostad> result = new Ostad_Bll().Select();
dataGridView1.DataSource = result;

ghasem110deh
دوشنبه 08 تیر 1394, 10:56 صبح
چرا دیتاتیبل استفاده کردی در صورتی که به نظر من وقتی داری از EF استفاده میکنی کلا بی خیال دیتاتیبل و دیتاست شو چون تمام داده ها به صورت شئ گرا در دسترس هستند.


سلام و ممنون ...
یعنی چجوری ؟ الان اگه از دیتاتیبل استفاده نکنم باید چجوری از این لایه پاس بدم به bll ؟

Mahmoud.Afrad
دوشنبه 08 تیر 1394, 13:11 عصر
به جای دیتاتیبل از IEnumerable<T> و یا IQueryable<T> استفاده کن(T نوع entity مورد نظر هست) که میتونی به دیتاسورس نسبت بدی. طبق کد پست قبلیم.

ghasem110deh
دوشنبه 08 تیر 1394, 14:27 عصر
به جای دیتاتیبل از IEnumerable<T> و یا IQueryable<T> استفاده کن(T نوع entity مورد نظر هست) که میتونی به دیتاسورس نسبت بدی. طبق کد پست قبلیم.

من این دو تا رو زدم :


var Table = (from tb in Con.Ostad.AsEnumerable()
select new
{
Id = tb.O_Id,
Name = tb.Name,
Family = tb.Family,
}).Distinct();
//IEnumerable<Ostad> result = from p1 in Con.Ostad
// join p2 in Con.Dars on p1.Dars_Id equals p2.D_Id into list1
// from l1 in list1.DefaultIfEmpty()
// select new { p1.O_Id, p1.Name, p1.Family, p1.Dars };
//return result;


اولی رو که فعاله نمی دونم چطوری باید توی ui بدم به دیتاسورس ... هر جور میزنی خطا میده !

کدهای دومی که الان غیر فعاله به return گیر میده !؟

یه مثال کامل بزنم ، بی زحمت :لبخند:

Mahmoud.Afrad
دوشنبه 08 تیر 1394, 16:23 عصر
از اونجایی که در select داری new میکنی و بعضی ستونها رو انتخاب میکنی و چون داری در متد این کار رو انجام میدی نمیتونی بدون نوع سلکت کنی. در سلکتی که انجام دادی مقادیر بدون نوع خواهند بود. ولی اگر خود tb رو سلکت کنی مشکلی نخواهی داشت.
اگر هم میخواهی برخی از ستونها رو سلکت کنی بایست یک کلاس برای اینکار ایجاد کنی با پراپرتی های مورد نیاز

public class ClassOstadView
{
public int Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
}


حالا متد مورد نظرت رو به صورت زیر اصلاح کن.(در سلکت شئ جدیدی از کلاس بالا ایجاد و مقدار دهی کن.
نوع برگشتی هم مجموعه ای از کلاس بالا هست

public IEnumerable<ClassOstadView> GetListOfOstad()
{
IEnumerable<ClassOstadView> table =
(from tb in Con.Ostad
select new ClassOstadView()
{
Id = tb.O_Id,
Name = tb.Name,
Family = tb.Family
}).Distinct();

return table;
}

اگر لیستی از اساتید به صورت Distinct میخواهی باید مشخص کنی بر اساس چه مشخصه ای Distinct انجام بشه.
برای انتساب به دیتاگریدویو هم کافیه مقدار بازگشتی متد رو به دیتاسورس بدی

dataGridView1.DataSource = GetListOfOstad();




برای کوئری بعدی هم به همین صورت عمل کن

public class ClassOstadJoinDarsView
{
public int OstadId { get; set; }
public string OstadName { get; set; }
public string OstadFamily { get; set; }
public string Dars { get; set; }
}

public IEnumerable<ClassOstadJoinDarsView> GetListOfOstadHaveDars()
{
IEnumerable<ClassOstadJoinDarsView> result =
from p in Con.Ostad
join d in Con.Dars on p.Dars_Id equals d.D_Id into joinResult
from item in joinResult.DefaultIfEmpty()
select new ClassOstadJoinDarsView
{
OstadId = p.O_Id,
OstadName = p.Name,
OstadFamily = p.Family,
Dars = p.Dars
};

return result;
}

اگر لیست اساتیدی که درس دارند رو میخوای و روابط جداول و موجودیتهای EF رو اعمال کردی راحت تر از اینها میشه لیست اساتیدی که درس دارند رو بدست آورد.

ghasem110deh
دوشنبه 08 تیر 1394, 18:57 عصر
من اینو توی لایه دال نوشتم :


public class Ostad_DarsView
{
public int OstadId { get; set; }
public string OstadName { get; set; }
public string OstadFamily { get; set; }
//public string Dars { get; set; }
}
public IEnumerable<Ostad_DarsView> GetListOfOstad()
{
IEnumerable<Ostad_DarsView> table =
(from tb in Con.Ostad
select new Ostad_DarsView()
{
OstadId = tb.O_Id,
OstadName = tb.Name,
OstadFamily = tb.Family
}).Distinct();
return table;
}


اینو توی bll نوشتم :


public IEnumerable<Dars_Dal.Ostad_DarsView> Select()
{
return new Dars_Dal().GetListOfOstad();
}


اینم تو فرم :



void Ostad_Show()
{
dataGridView1.DataSource = new Ostad_Bll().Select();
}


منتها این خطا رو میده (عکس ضمیمه)

Mahmoud.Afrad
دوشنبه 08 تیر 1394, 21:38 عصر
میتونی نتیجه رو با tolist به لیست تبدیل کنی تا مشکل برطرف بشه ولی توصیه میکنم اول Distinct کنی و بعد select new رو انجام بدی

public IEnumerable<Ostad_DarsView> GetListOfOstad()
{
IEnumerable<Ostad> distinctRecords =
(from tb in Con.Ostad
select tb).Distinct();

IEnumerable<Ostad_DarsView> result =
from item in distinctRecords
select new Ostad_DarsView
{
OstadId = tb.O_Id,
OstadName = tb.Name,
OstadFamily = tb.Family
};
return result;
}

RmeXXXXXXXXX
دوشنبه 08 تیر 1394, 22:39 عصر
استفاده از IQueryable<T> همیشه مفید نیست. دقت کنید که این نوع خروجی هیچ رکوردی را تا متد ToList و یا امثالهم فراخوانی نشوند هیچ مقداری رو از دیتابیس دریافت نمیکنند به نحو دیگه هیچ کاری با دیتابیس ندارند. در نگاه اول بنظر خیلی عالی هستند بدین صورت که چندین شرط (کوئری یا ویو) رو با تنها یک ارجاع به بایگاه داده بدست خواهیم آورد. توصیه موکد اینه که فقط در یک لایه از IQueryable<T> استفاده کنید و بین لایه پاس داده نشود به عبارت دیگه متدی با دسترسی public و خروجی IQueryable<T> نباید درکد شما باشد. چرا؟ چون یک کوئری یک طرف باز رو به لایه بالاتر پاس میدهیم که هیچ چیز در مورد خروجی اون قابل حدس زدن نیست. و به اطلاعات لایه پائینی (مواردی که رو کوئری انجام داده) نیاز خواهد بود. این امر پیچیدگی کدهای شما را بالا خواهد برد و لایه ها رو درهم تنیده خواهد کرد. از ICollection<T> یا IList<T> استفاده نمائید. تا همیشه یک جواب بسته رو تحویل دهید نه چیزی که معلوم نیست در بین لایه ها چی به سرش اومده.
در مورد نمایش در دیتاگیرید ویو هم بگم که شما باپیمایش توسط حلقه ها(foreach متداول تره) یک ICollection میتونید سطرها و ستونهای کاملا سفارشی برای دیتاگیردویو تعیین کنید.

ghasem110deh
سه شنبه 09 تیر 1394, 03:04 صبح
از هر دو عزیز ممنون :)
-----------------------



به عبارت دیگه متدی با دسترسی public و خروجی IQueryable<T> نباید درکد شما باشد
حتی اگه بریزیم توی List<> ؟
و اینکه یه طرفشون بازه یعنی چی ... بی زحمت بیشتر توضیح بدین !

و دو تا سوال کلی دیگه :

1- اصلا نوشتن EF بصورت سه لایه مزیتی داره ؟
چون کدهاشو توی خود فرم خیلی راحت تر نوشتم و تموم شد (رو حساب بیکاری گفتم سه لایه کنم ... خیلی سخت تر شد)

2- الان جوین (جدول ها رو) رو توی dal انجام میدم ، اما ظاهرا طریقه درستش اینه که توی bll باشه !؟
کار درستی هست کل جدول ها رو بخونی بعد پاس بدی به bll و اونجا جوین رو انجام بدیم ؟ (تو EF)

Mahmoud.Afrad
سه شنبه 09 تیر 1394, 03:24 صبح
مدل EF رو میشه لایه Data access در نظر گرفت. در اینصورت کدهایی Bll که شما نوشتی از بین میره (کار خاصی هم انجام نمیدن) و کدهایی که شما به عنوان DAL نوشتی میشن Bll.
برای join اگر کوئری ها رو در Bll بنویسی مشکلی نخواهی داشت.

ghasem110deh
سه شنبه 09 تیر 1394, 11:41 صبح
مدل EF رو میشه لایه Data access در نظر گرفت. در اینصورت کدهایی Bll که شما نوشتی از بین میره (کار خاصی هم انجام نمیدن) و کدهایی که شما به عنوان DAL نوشتی میشن Bll.
برای join اگر کوئری ها رو در Bll بنویسی مشکلی نخواهی داشت.

این درسته ... در واقع الان بیخودی یه لایه اضافه کردم (کاربردی هم نداره) :تشویق:
ممنون !

ghasem110deh
شنبه 13 تیر 1394, 20:51 عصر
سلام
این خطا واسه چیه ؟ (به نوع int گیر میده)

davidrobert
شنبه 13 تیر 1394, 22:39 عصر
برای اینکه به مقدار int گیر نده به این صورت بنویسید.
ostadars=convert.toint32(item.dars_id),
تا خطا رفع بشه.

ghasem110deh
یک شنبه 14 تیر 1394, 01:20 صبح
در مورد نمایش در دیتاگیرید ویو هم بگم که شما باپیمایش توسط حلقه ها(foreach متداول تره) یک ICollection میتونید سطرها و ستونهای کاملا سفارشی برای دیتاگیردویو تعیین کنید.

یه همچین چیزی میشه :

foreach (var result in students) {
Console.WriteLine(
"Couse: {0}, Student: {1} {2}",
result.Title,
result.Person.FirstName,
result.Person.LastName);
}

تاثیری تو سرعت نداره ...