שבט

TableAdapter, Multiple Result Sets and output Parameters

היה היה פרוייקט, שבו ניגשנו מהקוד ל-DB באמצעות strongly typed Dataset (קבצי XSD). למי שלא יודע מדוע כדי להשתמש בשיטה זו כדי לגשת ל-DB, אפשר לומר שזה מאותה סיבה שאנחנו מעדיפים לריב עם בן זוגנו בבית ולא במסעדה איטלקית אופנתית – באמצעות קבצי XSD אפשר למצוא אי התאמות בין DB לקוד בזמן קומפילציה ולא בזמן ריצה.

הפרוייקט חי לו שנים רבות בהשקט ובשלוה כאשר קבצי ה-XSD ממלאים את תפקידם נאמנה בהעברת נתונים אל ומה-DB. אלא, שכדרכם של פרוייקטים, באחד הימים חלה לפתע תפנית בעלילה. לפתע פתאום, דרישות הלקוח חייבו שינוי באחת ה-SP של המערכת, וכעת ה-SP היתה צריכה להחזיר שני Result sets. מיד נערכה בדיקה קצרה שבסופה התברר שקבצי XSD לא יכולים להתמודד עם תפנית מסעירה שכז – המתודה של strongly typed Dataset אומרת שכל פניה ל-DB ממופה ל-DataTable אחד בלבד! בעיה.

למשך זמן קצר חלפה במוחי המחשבה כי אולי זה הזמן להתנסות ב-LINQ. אולם זמני לא היה בידי, ואינני מכירה את LINQ מספיק טוב כדי לדעת אם וכיצד הוא יכול להתמודד עם השינוי המרנין הלזה. על כן החלטתי לדבוק במתודה הקיימת בפרוייקט, ולחפש ברחבי הרשת כיצד ניתן לקבל שני Result sets.

המקור הראשון שנתקלתי בו היה שאלה זהה לשלי:

I am using Visual Studio 2008 and strongly typed datasets.

My stored procedure returns 2 result sets (it has two select statements in
it). how can I receive and transfer both result sets into two strongly
typed datatables with only one database call?

התשובה הראשונה נתנה את הדרך: צריך להשתמש ב-DataAdapter במקום ב-TableAdapter. היא גם נתנה קטע קוד רלוונטי. הבעיה היתה שלא היה מספיק ברור איפה בדיוק לשים אותו. למרבה השמחה, התשובה הבאה נתנה קישור לקטע קוד עם הסבר על הקונטקסט: צריך ליצור הרחבה של מחלקת ה-Table Adapter הרלוונטית, ע”י שימוש ב-partial class, ושם ליצור מתודה שתקבל את ה-DS (קובץ ה-XSD), כדי שהיא תוכל למלא אותו ע”י ה-DataAdapter. כך, ע”י שילוב בין שני קטעי הקוד, וקצת אילתור (למשל, אני לא הצלחתי להשתמש באובייקט ה-connection כמו שמשתמשים בו בדוגמאות הנ”ל, אז יצרתי אובייקט חדש), הצלחתי ליצור קוד שאמור לקבל שני Result sets.

אבל בזאת לא תמו תלאותיי, מפני שה-SP שלי לא היתה כמו אלה שבדוגמאות: היא גם רצתה לקבל פרמטרים. טוב. בסדר. אפשר לחיות עם זה. אבל היא גם רצתה פרמטר מסוג מיוחד: output parameter! נו, לכבוד מאורע חגיגי זה, יצאתי שוב לשיטוטיי ברשת של דוטנט. מצאתי שני מאמרים שמסבירים איך לקבל בחזרה גם את פרמטר הפלט. הראשון היה בכיוון, אבל לא לגמרי הצליח לי. השני היה ממש יסודי וברור, ובזכותו הצלחתי לסיים בהצלחה את ההרפתקה המרננת שלי:

public int FillTables(ref DAL ds, Guid code,ref int? output)
{
int returnValue = 0;
SqlDataAdapter sqlDa = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand();
try
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = “My_Stored_Procedure”;

//Add @user_code parameter:
SqlParameter parm = new SqlParameter(“@user_code”, SqlDbType.UniqueIdentifier);
parm.Value = code;
parm.Direction = ParameterDirection.Input;
cmd.Parameters.Add(parm);

//Add @succes parameter:
parm = new SqlParameter(“@succes”, SqlDbType.Int);
parm.Value = output;
parm.Direction = ParameterDirection.Output;
cmd.Parameters.Add(parm);

cmd.Connection = GetConnection();
sqlDa.SelectCommand = cmd;

// add table mappings to the SqlDataAdapter – neede so they get filled with the SP resultSet
sqlDa.TableMappings.Add(“Table”, “Name1”);
sqlDa.TableMappings.Add(“Table1”, “Name2”);
cmd.Connection.Open();

// after this line code is executed, the two DataTables(Name1 and
// Name2) are filled with the corresponding result sets

int rowsAffected = sqlDa.Fill(ds);

// get the result of the output parameter
output = (int) cmd.Parameters[“@succes”].Value;
}
catch (Exception ex)
{
aDebugInfo = ex.Message;
aDebugEXInfo = ex.ToString();
}
cmd.Connection.Close();
return returnValue;
}

אמנם, כפי שניתן לראות מהקוד, אנחנו מאבדים כאן קצת את ה-strong type מבחינת העברת הפרמטרים – אנחנו חוזרים לשיטת ה-string-ים של ADO.NET, ושוב חוזרת סכנת השגיאות בזמן ריצה. אולם מה שבכל זאת נשאר strongly typed הוא ה-DataTable המתקבל:

DAL ds = new DAL();
adapter.FillTables( ref ds, (Guid)code, ref ouput);

// We need UserGroups Table
if (ds.Name2!= null && ds.Name2.Count>0)
{

  1. comments = ds.UserGroups.codeColumn;
    1. }

כפי שניתן לראות מהקוד שקורא למתודה דלעיל, אנחנו מקבלים את שמות ה-datatable-ים בקוד, כמו גם את שמות העמודות. אז אמנם ותירנו עם strong typing של שמות הפרמטרים, אבל קיבלנו שני result sets וגם פרמטר פלט – אז אנחנו שמחים חיוך

כתבו תגובה

כתובת הדוא"ל שלכם לא תוצג.