משיב מוביל
איך ניגשים לטבלה דינאמית בLINQ?

שאלה
-
אני צריכה לגשת לטבלה, אבל שם הטבלה תלוי במשתנה שאקבל..
הייתי רוצה לעשות את הקוד הבא..
public double GetGeneralItem(int PCode, int SCode) { string tableName = GetSTable(SCode); var generalItem = _db.tableName.Where(r => r.PCode == PCode).Select(r => r.generalItem).FirstOrDefault(); if (generalItem != null) return (double) generalItem; return 0; } public string GetSTable(int SCode) { return _db.Secs.Where(s => s.SCode== SCode).Select(s => s.SName).FirstOrDefault(); }
כמובן ש _db.tableName לא חוקי..
איך כן אפשר לעשות את זה?
יום רביעי 16 מאי 2012 11:58
תשובות
-
ניתן להריץ שאילתת SQL דרך ה-Context של Entity Framework
לדוגמא, אם את משתמשת ב-Entity Framework Code First אזיי הקוד נראה כך:
context.Database.SqlQuery<string>("SELECT Name FROM Users").First()
- סומן כתשובה על-ידי Eran Sharvit יום ראשון 20 מאי 2012 19:52
יום חמישי 17 מאי 2012 21:47מנחה דיון -
לקח לי קצת זמן..
context.Database לא היה קיים אצלי.. אז בדקתי באינטרנט וראיתי שהוא קיים רק dbContext
ואני משתמשת ב httpContext - אז חיפשתי מה המקבילה ומצאתי את הקוד הבא שאכן עובד..
var generalItem = _db.ExecuteStoreQuery<double>("SELECT generalItem FROM " + tableName + " WHERE PCode=" + PCode).FirstOrDefault();
תודה על הכיוון!
- סומן כתשובה על-ידי Eran Sharvit יום ראשון 20 מאי 2012 19:52
יום ראשון 20 מאי 2012 06:49
כל התגובות
-
אני מניח ששתי הטבלאות הינן מסוג שונה. במידה וזה המצב אזיי אני יכול לחשוב על שתי אפשרויות:
1) ExpressionTree - תשתית המאפשרת לבנות שאילתות LINQ בזמן ריצה. את יכולה לקרוא על זה כאן. היתרון הוא שאפשר לעשות הרבה דברים מתקדמים שאי אפשר בדרך אחרת אבל מצד שני זה דורש לא מעט קידוד.
2) להשתמש בעובדה שלשתי הטבלאות יש Properties בשם PCode וכן generalItem ולהגדיר עבורן interface משותף. באופן כזה את יכולה לבנות את השאילתא פעם אחת ולהפעילה על טבלאות שונות. לדוגמא:
public interface IObject { int ID { get; set; } string Name { get; set; } } public class User : IObject { public int ID { get; set; } public string Name { get; set; } } public class Group : IObject { public int ID { get; set; } public string Name { get; set; } } class MyContext : DbContext { public DbSet<User> Users { get; set; } public DbSet<Group> Groups { get; set; } } class Program { static void Main(string[] args) { using (MyContext context = new MyContext()) { Console.WriteLine(ExecQuery(context, "Users")); Console.WriteLine(ExecQuery(context, "Groups")); } } public static object ExecQuery(MyContext context, string tableName) { if (tableName == "Users") { return ExecQuery(context.Users); } else if (tableName == "Groups") { return ExecQuery(context.Groups); } else { throw new ArgumentException("Invalid table name"); } } public static object ExecQuery<T>(IQueryable<T> q) where T: class, IObject { return q.Where(x => x.ID > 0).Select(x => x.Name).FirstOrDefault(); } }
יום רביעי 16 מאי 2012 22:07מנחה דיון -
דבר ראשון תודה על התשובה, מעריכה את ההשקעה בכתיבת ה interface.. והמחשבה..
אבל נראה לי שלא הבנת אותי, או שאני לא הבנתי את התשובה (ייתכן מאוד..)
אז אני אנסה להסביר טוב יותר וגם לצרף תמונה שמסכמת איך נראה הדטה בייס..
יש לי קרוב לארבעים טבלאות בDB שהמבנה הבסיסי שלהם זהה עם שינויים קלים אבל מייצגות טיפוסים שונים בDB.. לכל טבלה יש SCode זה קוד מזהה ו generalItem - זה נתון כללי על כל רשומה שנותן לי ההערכה לגביו.
יש לי טבלה נוספת Secs שבה יש קוד טיפוס ושם טבלת הטיפוס
בשאילתא אני מקבלת SCode ו PCode וכך אני ניגשת דבר ראשון לטבלת הSecs לפי הSCode ושם בודקת לאיזה טבלה מתוך ה40 לגשת,
ואז אני צריכה לגשת לטבלה (שנמצאת במשתנה דינאמי) ולשלוף את הנתון generalItem לפי הPCode.
בT-SQL מדובר בסה"כ ב-2 שורות...
@tblName = select tblName from Secs where SCode = @SCode
@generalItem = select generalItem from @tblName where PCode=@Pcode
ב LINQ אני לא מכירה דרך לעשות את זה. ו-2 הדרכים שהצעת.. מורכבות מידי.. (או לא מתאימות, בכל אופן לפי מה שעשית אני יכולה לחסוך את הקלאס -
ולעשות switch על SCode ולהחזיר את הנתונים מהטבלה
אין משהו פשוט יותר?
יום חמישי 17 מאי 2012 06:25 -
מה הסוג של המשתנה _db? האם את משתמשת ב-EntityFramework?
יום חמישי 17 מאי 2012 10:58מנחה דיון -
כן. אני משתמשת ב EntityFrameworkיום חמישי 17 מאי 2012 11:05
-
ניתן להריץ שאילתת SQL דרך ה-Context של Entity Framework
לדוגמא, אם את משתמשת ב-Entity Framework Code First אזיי הקוד נראה כך:
context.Database.SqlQuery<string>("SELECT Name FROM Users").First()
- סומן כתשובה על-ידי Eran Sharvit יום ראשון 20 מאי 2012 19:52
יום חמישי 17 מאי 2012 21:47מנחה דיון -
לקח לי קצת זמן..
context.Database לא היה קיים אצלי.. אז בדקתי באינטרנט וראיתי שהוא קיים רק dbContext
ואני משתמשת ב httpContext - אז חיפשתי מה המקבילה ומצאתי את הקוד הבא שאכן עובד..
var generalItem = _db.ExecuteStoreQuery<double>("SELECT generalItem FROM " + tableName + " WHERE PCode=" + PCode).FirstOrDefault();
תודה על הכיוון!
- סומן כתשובה על-ידי Eran Sharvit יום ראשון 20 מאי 2012 19:52
יום ראשון 20 מאי 2012 06:49