Клубове Дир.бг
powered by diri.bg
търси в Клубове diri.bg Разширено търсене

Вход
Име
Парола

Клубове
Dir.bg
Взаимопомощ
Горещи теми
Компютри и Интернет
Контакти
Култура и изкуство
Мнения
Наука
Политика, Свят
Спорт
Техника
Градове
Религия и мистика
Фен клубове
Хоби, Развлечения
Общества
Я, архивите са живи
Клубове Дирене Регистрация Кой е тук Въпроси Списък Купувам / Продавам 18:56 13.06.24 
Клубове/ Компютри и Интернет / .NET Всички теми Следваща тема Пълен преглед*
Информация за клуба
Тема reflection в stored procedures [re: pp]
Автор шeф нa Coди Дeвня (full optional)
Публикувано07.08.03 13:58  



Главния недостатък на ползването на SQL stored procedures от С# код е това че трявба да напаснеш (match) прекалено много типове. И се налага да пишеш дълги wrapper functions. Ако ползваш stored procedures доста, знаеш колко е досадно да описваш всеки параметър: име, тип, размер и т.н. ... освен това ако промениш процедурата и пак трябва да ходиш да променяш кода в data service layer-a. Примерно имаш следната процедура:

CREATE PROCEDURE GetData @ID int
AS
SELECT * FROM DataTable WHERE [ID] = @ID

за да извикаш тази процедура обикновенно и правиш wrapper функция като тази:

Recordset GetData(Connection cn, int nID)
{
Command cm = new Command();
cm.ActiveConnection = cn;
cm.CommandText = "GetData";
cm.CommandType = adCmdStoredProc;

Parameters params = cm.Parameters;
params.Append(cm.CreateParameter("@RETURN_VALUE", adInteger, adParamReturnValue, 0);
params.Append(cm.CreateParameter("@ID", adInteger, adParamInput, 0);
params("@ID").Value = nID;

Recordset r = new Recordset();
r.CursorLocation = adUseClient;
r.Open ( cm, , adOpenStatic, adLockReadOnly );
r.ActiveConnection = null;
return r;
}


Този подход съвсем не е зле в ерата когато нямаше .NET, обаче сега като видиш половината ти екип през половината ден да пише такъв код и после половината му рипорт да е: "Емиии ... писах wrapper functions ..." и си викаш - отиде ми и производителност и deadlines и кво ли не ... и почваш да мъдриш некви гениални идеи ... примерно: да напишеш генератор който автоматично прави wrapper functions чрез SQLDMO ... или пък да правиш XML дефиниции на процедурите и после с XSLT (за което според някой хора в този форум аз изобщо не съм бил чувал) да генерираш кода на wrapper function-a.

Но първите идеи не е задължително да са винаги най-подходящите ...

Как reflection променя цялата тази картинка ???!!!

Лесно може да си представиш как чрез reflection може да обходиш параметрите на дадена функция и да създадеш SqlCommand обект с респективните SqlParameter обекти. Всичко което трябва да направиш е да дефинираш функции които да представляват твоите процедури и останалото ще се прави от една utility function която динамично ще създава и конфигурира SqlCommand обекти по време на изпълнение на програмата за да се обръща към базата данни. Примерно нещо такова:

sealed class SqlCommandGenerator
{
private SqlCommandGenerator() {}

public static SqlCommand GenerateCommand(SqlConnection connection,
MethodInfo method, object[] values)
{
SqlCommand command = new SqlCommand(method.Name, connection);
command.CommandType = CommandType.StoredProcedure;

ParameterInfo[] parameters = method.GetParameters();

for (int i = 1; i < parameters.Length; i++)
{
SqlParameter sqlParameter = new SqlParameter();
sqlParameter.ParameterName = "@" + parameters[ i ].Name;
sqlParameter.Value = values[ i ];

command.Parameters.Add(sqlParameter);
}

return command;
}
}

Като имаш обект от тип Connection, метаданните на метода и стойностите на параметрите GenerateCommand генерира и изпълнява SqlCommand обект все едно че си го писал като сорс. Даже няма нужда да да ползвам типа на параметъра да получа SqlDbType за да дам типа на SqlParametera, защото SqlParameter вече има такава функционалност като подаваш Value и го прави вместо тебе.

След това трябва да извикаш GenerateCommand от GetData и да използваш генерираната команда:

public static DataSet GetData(SqlConnection connection, int Id)
{
MethodInfo methodInfo =
typeof(myDatabase).GetMethod("GetData",
new Type[] { typeof(SqlConnection), typeof(int) });

SqlCommand command =
SqlCommandGenerator.GenerateCommand(connection,
methodInfo, new object[] { Id });

DataSet dataSet = new DataSet();
SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
dataAdapter.Fill(dataSet);
return dataSet;
}

До тук добре ... обаче не е идеално защото пак ще ти се налага да правиш промени в кода ако се промени процедурата, примерно смениш името. Това лесно може да се реши ако се разходиш по стека и вземеш frame-а на въпросния метод. Наред с всички хубави неща в FCL, има еднa особено приятна функция, леко скрита ама това да не те притеснява, MehodBase.GetCurrentMethod. Тя ти връща MethodBase (MethodInfo или ConstructorInfo) за функцията която я вика. И става нещо такова:

public static DataSet GetData(SqlConnection connection, int Id)
{
SqlCommand command = SqlCommandGenerator.GenerateCommand
(connection, (MethodInfo) MethodBase.GetCurrentMethod(),
new object[] { Id });

DataSet dataSet = new DataSet();
SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
dataAdapter.Fill(dataSet);
return dataSet;
}

горе долу това е идеята макар че има случаи когато имаш безименни параметри или пък типовете на параметрите са леко различни от тези на метода или пък NULL values ... ама и те си имат решение - Attributes ...




XM TurboCT .. where comfort meets power

Цялата тема
ТемаАвторПубликувано
* Reflectioning Memo   04.08.03 11:14
. * Re: Reflectioning gruhal   04.08.03 12:27
. * Обикновено jamie   05.08.03 11:25
. * Re: Reflectioning шeф нa Coди Дeвня   05.08.03 20:18
. * Re: Reflectioning Memo   06.08.03 10:25
. * Re: Reflectioning pp   06.08.03 21:51
. * Re: Reflectioning gruhal   07.08.03 12:39
. * reflection в stored procedures шeф нa Coди Дeвня   07.08.03 13:58
. * Re: reflection в stored procedures Guru   07.08.03 19:33
. * Re: reflection в stored procedures rr   07.08.03 21:53
. * Re: reflection в stored procedures шeф нa Coди Дeвня   08.08.03 10:03
. * Re: reflection в stored procedures Daniel   08.08.03 10:57
. * Re: reflection в stored procedures Memo   08.08.03 11:09
Клуб :  


Clubs.dir.bg е форум за дискусии. Dir.bg не носи отговорност за съдържанието и достоверността на публикуваните в дискусиите материали.

Никаква част от съдържанието на тази страница не може да бъде репродуцирана, записвана или предавана под каквато и да е форма или по какъвто и да е повод без писменото съгласие на Dir.bg
За Забележки, коментари и предложения ползвайте формата за Обратна връзка | Мобилна версия | Потребителско споразумение
© 2006-2024 Dir.bg Всички права запазени.