PDA

View Full Version : تبدیل نوع عبارت نوشته شده با linq



alibabaei2
یک شنبه 06 شهریور 1390, 04:54 صبح
با سلام
چطوری میتونم دستور زیر رو که با linq نوشتم به string[] تبدیل نوع کنم
from us in Context.Users
join rl in Context.Roles
on us.RoleID equals rl.RoleID
where
us.UserID == userID
select rl.RoleName

با .ToString() و .ToArray() هم چیزی درست نشد

Saman Hashemi
یک شنبه 06 شهریور 1390, 09:02 صبح
var qry=from us in Context.Users
join rl in Context.Roles
on us.RoleID equals rl.RoleID
where
us.UserID == userID
select rl.RoleName
string rolename=qry.First().RoleName;
//يا براي يك مجموعه
foreach (var roleName in qry)
{
arrrolename[i]=rolename.ToString();
i++;
}

alibabaei2
یک شنبه 06 شهریور 1390, 15:50 عصر
ممنون مشکلم حل شد
یه سوال دیگه
.first اینجا چه کاری انجام میده؟

raziee
یک شنبه 06 شهریور 1390, 17:48 عصر
ممنون مشکلم حل شد
یه سوال دیگه
.first اینجا چه کاری انجام میده؟
@Saman Hashemi کدی که نوشتید زیاد جالب نیست.

string[] roleName = (from r in Context.Roles
where (from u in Context.Users
where u.UserID == userID
select u.RoleID).Contains(r.RoleID)
select r.RoleName).ToArray();

@alibabaei2 شما مگه تو جدول Users چند رکورد با UserId = 1 دارید؟ که میخواهید RoleID هاش رو دریافت کنید؟
ساختار جداولتون چطوریه؟
برای ارتباط بین جدول User و جدول Role جدولی با نام UserRoles ندارید؟

ونوس
شنبه 20 دی 1393, 13:57 عصر
سلام دوستان
من یک سوال دارم و آن هم این هست که چطور میشه یک عبارت string که شامل شرطهایی برای استفاده در قسمت شرط دستور select در linq بکار ببرم آخه فقط شرط boolean قبول می کنه .
ممنون

SabaSabouhi
شنبه 20 دی 1393, 15:02 عصر
سلام
linq خودش نمی‌تونه عبارت شما رو بخونه، البته می‌تونید خودتون این کار رو بکنید.
به این صورت که تابعی بنویسید که عبارت رو بگیره، محاسبه کنه و مقدار bool برگردونه که صد البته
مقرون به صرفه نیست. الگوریتم خودتون رو عوض کنید.
گمان می‌کنم شما می‌خواین شرط‌های پویا داشته باشین. من این کار رو بارها انجام دادم فقط کمی
باید روش کارتون رو عوض کنید و توصیه می‌کنم که از حالت عادی عبارت‌ها linq استفاده نکنید و بجاش از
lambda استفاده کنید.
یه نکته‌ی خیلی مهم هم اینه که برای این که تعداد queryهایی که به Database زده می‌شه رو حداقل کنید،
تا جایی که ممکنه بجای IEnumerableها از IQueriableها استفاده کنید.

صبا صبوحی

ونوس
یک شنبه 21 دی 1393, 08:56 صبح
سلام
مرسی عزیزم از راهنماییتون میشه یکم بیشتر توضیح بدهید یا یک کد برام بذارید .ممنون
.من باید با انتخاب 85 چک باکس شرطم را بسازم که عبارتهای شرطشون را نوشتم و شرط جستجو براساس انتخاب 85 چک باکس به حالت and و or هست

SabaSabouhi
یک شنبه 21 دی 1393, 14:36 عصر
سلام
اوه اوه، 85 تا چک باکس یه کم زیاده :)
اما دقیقاً من هم برای فیلترینگ فرم‌های لیستی همین کار رو می‌کنم.
شما با Lambda اگه کار کرده باشین Select شما در واقع تعدادی زیادی فراخوانی توابع به صورت پشت‌سرهم می‌شه.
فقط توجه کن به این که تا قبل از اعمال تمامی شرط‌ها ToList رو فراخوانی نکنی. چون ToList مقدار IQueryable رو به IEnumerable تبدیل می‌کنه
و به زبان ساده‌تر با Database ارتباط می‌گیره و اطلاعات رو به حافظه میاره. در حالی که باید کاری کنی که پس از اعمال تمام
شرط‌ها این اتفاق بیافته که فقط یک‌بار با Database ارتباط بگیری و حداقل تعداد سطر به حافظه بیاد. ( تاثیر بسیار زیادی تو سرعت برنامه داره )

و اما مراحل کار
ابتدا Query اصلی رو تولید کن و تو یه متغیر بریز. ( تا وقتی که IQueryable باشه تو دیباگ نمی‌تونی مستقیم خروجی رو ببینی )
اول با استفاده از using یه context ایجاد می‌کنیم.


using ( var entities = new Context() )



مثلاً می‌خوایم فهرست مشتریان رو داشته باشیم. ( که فعال باشن )


var queryable = entities.Persons.Where(x=>x.IsEnable )



حالا می‌خوایم فیلترش کنیم، مثلاً بر اساس فیلتر وضعیت تاهل. با این فرض که یه فیلد برای وضعیت تاهل داریم.
فرض می‌کنیم mariageStatus یک Enumeration از جنس EMariageStatus هست که مقادیر Nothing, Single, Married, Devorced رو داره.


if ( mariageStatus != EMariageStatus.Nothing )
queryable = queryable.Where ( x=>x.MariageStatus == mariageStatus )



بنابراین این شرط فقط وقتی که وضعیت تاهل انتخاب شده باشه اضافه می‌شه.
و حالا یه مثال برای وقتی که نیاز به Join به جدول دیگه داشته باشیم.
فرض کن یه جدول داریم برای فهرست فاکتورهایی که برای هر شخص صادر شده.
اگه بخواهیم فیلتری داشته باشیم که فقط لیست پرسنلی مشاهده شود که پس از یک تاریخ
فاکتوری برایشان صادر شده به این شکل عمل می‌کنیم.
invoiceDate متغیری است از جنس ?DateTime که اگه این فیلتر انتخاب نشده باشه null هست
و در غیر این صورت مقدار داره.


var queryableInvoices = entities.Invoices.Where( x=>x.InvoiceDate >= (DateTime)invoiceDate );



این خط یک IQueriable رو به صورت مستقل می‌سازه.
حالا با چک کردن شرط اون رو به لیست خودمون اضافه می‌کنیم.


if ( invoiceDate != null )
queryable = queryable.GroupJoin( queryableInvoices, person=>person.Id, invoice=>invoice.PersonId,
(person, invoices)=>new { person, firstInvoice = invoices.FirstOrDefault() } )
.Where ( x=>x.firstInvoice != null )
.Select ( x=>x.person );



تو این عبارت فقط در صورتی که تاریخ null نباشه، join انجام می‌شه و افرادی که پس از تاریخ داده شده فاکتوری نداشته باشن
از لیست خارج می‌شن.

تمام شرطها رو که چک کردین در آخر ToList رو بهش اضافه کنید تا یک query با whereها و joinها ساخته بشه و نتیجه نهایی
از بانک اطلاعات بازیابی بشه.


var list = queryable.ToList();




به همین راحتی، ضمن این که حداکثر سرعت اجرا و خوانایی کد رو هم به همراه داره.

صبا صبوحی

ونوس
یک شنبه 21 دی 1393, 15:21 عصر
مرسی عزیزم از راهنمایی خوبت . حالا اگه بخوام شرطی که از and و or کردن این چک باکس ها میسازه را ذخیره کنم تا بعد بخواد از همین عبارت شرطی برای قسمت شرط استفاده بشه دچار مشکل میشم چون این عبارت بصورت string باید ذخیره بشه و بعد where نمیتونه این string را برای خودش تفسیر کنه .برای این چالش من راه حلی پیدا نکردم

SabaSabouhi
دوشنبه 22 دی 1393, 16:30 عصر
سلام
تولید نرم‌افزار وقتی از حالت ساده و روتین خارج بشه، همیشه یه چالش هست و برنامه نویس باید آماده رویارویی با این چالش‌ها باشه.
اگه توجه کرده باشین، کلاس object که پدر تمام کلاس‌ها هست 3 تا متد virtual داره که یکیش ToString هست. پس تبدیل هر چیزی
به رشته یکی از امکانات اولیه زبان #C هست.
من از مساله‌ی شما استنباط کردم که برای این کار خاصی که دارین انجام می‌دین، کنترل‌هایی طراحی کرده باشین. ( من همین کار رو کردم )
و این کنترل‌ها باید بتونن مقدار فعلی رو به رشته تبدیل کنن و برای مقدار دهی اجرای بعدی از رشته بخونن.
شما باید این عملیات رو پیاده سازی کنید.

* خواند مقدار اولیه به صورت رشته از دیتابیس
* دادن مقدار اولیه ( رشته ) به کنترل
* خواندن مقدار کنترل ( iqueriable ) برای کار اصلی
* خواندن مقدار کنترل ( رشته ) برای ذخیره در دیتابیس

نکته: زیاد فکر کنید، با دقت طراحی کنید، ساده کد نویسی کنید.

صبا صبوحی