Аннотация:
В статье подробно рассматривается состав и способы применения пространства имён Rsdn.Framework.Data, представляющего собой высокоуровневую обёртку над ADO.NET.
30.04.04 06:49: Перенесено из '.NET Projects'
Если нам не помогут, то мы тоже никого не пощадим.
Data Provider for Oracle не добавлен в приведённый выше список не из соображений консолидации с Microsoft в священной борьбе против Oracle, а по причине реализации этого провайдера в отдельной сборке, подключение которой приведёт так же к необходимости её подключения ко всем проектам, которые будут использовать Rsdn.Framework.Data
M>Data Provider for Oracle не добавлен в приведённый выше список не из соображений консолидации с Microsoft в священной борьбе против Oracle, а по причине реализации этого провайдера в отдельной сборке, подключение которой приведёт так же к необходимости её подключения ко всем проектам, которые будут использовать Rsdn.Framework.Data
M>Не понял откуда взялся такой вывод?
Такой вывод взялся после проведения ряда научных экспериментов и получения сообщения вида 'The type 'System.Data.OracleClient.*****' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Data.OracleClient'.', которое появляется в некоторых ситуациях наследования или доступа к мемберам класса, тип которых определён в неподключённой сборке. При текущей архитектуре библиотеки (которая уже успела притерпеть кучу изменений) данная ситуация возможна только при умышленном использовании Oracle провайдера. Т.е. вывод сделан неверно
Спасибо за замечание Статья и библиотека приведены в соответсвие. Заодно для любителей борланды пример подключения провайдера для Oracle заменён на подключение Borland Data Providers for .NET (BDP.NET).
... << RSDN@Home 1.1 beta 2 >>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Игорь Ткачёв, Вы писали:
ИТ>Статья: ИТ>Пространство имён Rsdn.Framework.Data
ИТ>Авторы: ИТ> Игорь Ткачёв
ИТ>Аннотация: ИТ>В статье подробно рассматривается состав и способы применения пространства имён Rsdn.Framework.Data, представляющего собой высокоуровневую обёртку над ADO.NET.
Я вот тут написал свою маленькую либe для создания и выполнения Batch SQL запросов...
думаю что пригодиться всем кто будет разрабатывать серъезные системы: здесь
конечно есть несколько ограничений, но вы зато сможете легко и быстро формировать запросы...
Основная идея:
— запрос может состоять из нескольких последовательных вызовов TSQL stored procedures
— процедуры могут иметь общие параметры
— результат выполнения одной прцедуры может быть передан как параметр в другую процедуру
— вызов может быть сгенерен в виде текста или сделан при помощи встроенных средств NET Framework
— нейтив методы вызова сторед процедур рекомендуеться использовать только для "тяжелых" типов данных таких как image, text, ntext
— после выполнения запроса параметры переданные в запрос и которые имеют [out] маркер вернуться с новыми значениями.
— автоматическая выкачка параметров сторед процедур, что позволяет не заниматьс нудным делом: прописыванием параметров при запросе.
— результат приходит в виде датасета
— все сделано с расчетом на использование при ремоутинге... работа через интерфейсы...
как на меня законченная разработка... может кому идея что доработать в голову прийдет то излагайте...
IT>А можно примерчик как это использовать? а то с телепатическими способностями сегодня как-то туго.
надо тренироваться за пару лет общения на РСДН-не можно не плохие развить
Здравствуйте, Tom, Вы писали:
IT>>А можно примерчик как это использовать? а то с телепатическими способностями сегодня как-то туго. Tom>надо тренироваться за пару лет общения на РСДН-не можно не плохие развить
Телепалке тоже иногда отдых нужен
... << RSDN@Home 1.1 beta 2 >>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, AlexK, Вы писали:
AK>>Я вот тут написал свою маленькую либe для создания и выполнения Batch SQL запросов...
IT>А можно примерчик как это использовать? а то с телепатическими способностями сегодня как-то туго.
все просто до безобразия:
открываеш архив... достаеш сорсы...
ищеш в сорсах файлик: TestSuite.cs и видеш набор тестов на которых гонялась либа...
они же и примеры использования...
Здравствуйте, AlexK, Вы писали:
IT>>А можно примерчик как это использовать? а то с телепатическими способностями сегодня как-то туго.
AK>все просто до безобразия: AK>открываеш архив... достаеш сорсы... AK>ищеш в сорсах файлик: TestSuite.cs и видеш набор тестов на которых гонялась либа... AK>они же и примеры использования...
А... вот оно как. К сожалению, у нас сегодня и с трудолюбием проблема
... << RSDN@Home 1.1 beta 2 >>
Если нам не помогут, то мы тоже никого не пощадим.
ИТ>Авторы: ИТ> Игорь Ткачёв
ИТ>Аннотация: ИТ>В статье подробно рассматривается состав и способы применения пространства имён Rsdn.Framework.Data, представляющего собой высокоуровневую обёртку над ADO.NET.
У меня есть вопрос. К примеру, я хочу исполнить процедуру sp_help, или группу запросов, которая вернёт несколько результатов, и получить списки объектов, связанные с этими результатами. В данный момент, методы ExecuteList и ExecuteSpList делают только один "проход" и не вызывают IDataReader.NextResult.
Может стоит добавить в DbManager метод типа ArrayList GetObjectList(IDataReader reader, Type type).
В таком случае, можно было бы написать так:
IDataReader reader = db.ExecuteSpReader("sp_help", "MyTable");
ArrayList tables = db.GetObjectList(reader, typeof(MyTableInfoClass));
ArrayList columns = db.GetObjectList(reader, typeof(MyColumnInfoClass));
reader.NextResult(); // we are skipping this result set because we want go to index information
reader.NextResult(); // we are skipping this result set because we want go to index information
reader.NextResult(); // we are skipping this result set because we want go to index information
reader.NextResult(); // we are skipping this result set because we want go to index information
ArrayList indexes = db.GetObjectList(reader, typeof(MyIndexInfoClass));
и т.д.
Другой вариант — добавить аргумент Type[] types в методы ExecuteList и ExecuteSpList.
Тогда бы мы имели следующее:
// null type means that we will skip next result set.
Type[] types = new Type[3] {typeof(MyTableInfoClass), typeof(MyColumnInfoClass), null, null, null, typeof(MyIndexInfoClass)}
ArrayList objects = db.ExecuteSpList(types, "sp_help", "MyTable"); // returns ArrayList of ArrayLists
MyTableInfoClass table = (ArrayList[0] as ArrayList)[0];
table.Columns = (ArrayList[1] as ArrayList);
table.Indexes = (ArrayList[5] as ArrayList);
Здравствуйте, Павел Бондарчук, Вы писали:
ПБ>Как вам такая идея?
Добавь в конец MapData.cs следующие методы:
public static IList MapList(IDataReader reader, IList list, Type type)
{
if (reader.Read())
{
Mapping.DataReaderSource drs = new Mapping.DataReaderSource(reader);
Mapping.TypeDescriptor td = Mapping.TypeDescriptor.GetDescriptor(type);
do
{
object o = td.CreateInstance();
MapData.Map(drs, reader, td, o);
list.Add(o);
} while (reader.Read());
}
return list;
}
public static ArrayList MapList(IDataReader reader, Type type)
{
ArrayList arrayList = new ArrayList();
MapList(reader, arrayList, type);
return arrayList;
}
Использовать можно будет так:
using System;
using System.Data;
using System.Collections;
using Rsdn.Framework.Data;
using Rsdn.Framework.Data.DataProvider;
namespace Example
{
public class Category
{
[MapField(Name = "CategoryID")]
public int ID;
public string CategoryName;
[MapField(IsNullable = true)]
public string Description;
}
class Test
{
static void Main()
{
using (DbManager db = new DbManager())
using (IDataReader dr = db.ExecuteReader(@"
SELECT
CategoryID,
CategoryName,
Description
FROM Categories
SELECT
CategoryID,
CategoryName
FROM Categories"))
{
ArrayList al = MapData.MapList(dr, typeof(Category));
foreach (Category c in al)
Console.WriteLine("{0,2} {1,-15} {2}", c.ID, c.CategoryName, c.Description);
if (dr.NextResult())
{
al = MapData.MapList(dr, typeof(Category));
foreach (Category c in al)
Console.WriteLine("{0,2} {1,-15} {2}", c.ID, c.CategoryName, c.Description);
}
}
}
}
}
Я это попозже выложу в новой версии.
... << RSDN@Home 1.1 beta 2 >>
Если нам не помогут, то мы тоже никого не пощадим.
Возвращая IDataReader, вы ставете пользователя перед необходимостью запихивать это в try/catch блок, соответственно заставляете его обрабатывать OleDbException, SqlException, ... и т.д. (Мы же абстрагировались от провайдера?) Это неудобно. Сделайте прокси-класс для IDataReader что бы он выбрасывал только Ваше исключение и сделайте соответственно свою иерархию исключений. Тогда придётся отлавливать только одно исключение.
Первым делом хочется поблагодарить за замечательную библиотечку . Очень интересно и полезно!
Теперь к трабле...
Функция DbManager.CreateParameters() не хочет работать со структурами...
public class testID
{
public int ID;
public testID(int ID)
{
this.ID = ID;
}
}
// .....
IDbDataParameter[] pars =
manager.CreateParameters(new testID(51));
И в итоге имеем параметром со значением, например, 4090216
Щас полезем в исходники ковыряться
Здравствуйте, SiAVoL, Вы писали:
SAV>Теперь к трабле...
Странно, вот такой тест у меня работает как часы
public class testID
{
public int ID;
public testID(int ID)
{
this.ID = ID;
}
}
[Test]
public void CreateParameters()
{
using (DbManager db = new DbManager(ConfigurationString))
{
IDbDataParameter[] pars = db.CreateParameters(new testID(51));
Console.WriteLine(pars[0].Value);
Assert.IsTrue((int)pars[0].Value == 51);
}
}
... << RSDN@Home 1.1 beta 2 >>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, voxel3d, Вы писали:
V> Возвращая IDataReader, вы ставете пользователя перед необходимостью запихивать это в try/catch блок, соответственно заставляете его обрабатывать OleDbException, SqlException, ... и т.д. (Мы же абстрагировались от провайдера?) Это неудобно. Сделайте прокси-класс для IDataReader что бы он выбрасывал только Ваше исключение и сделайте соответственно свою иерархию исключений. Тогда придётся отлавливать только одно исключение.
К сожалению, между исключениями, порождаемыми разнами провайдерами, практически нет ничего общего. Следовательно, всё что можно сделать — это выбрать из такого исключения сообщение и само сообщение сохранить как вложенное. Пользователю всё равно придётся самостоятельно всё это обрабатывать, чтобы добраться до сути. Поэтому, особого смысла изобретать рапер и всё усложнять нет.
... << RSDN@Home 1.1 beta 2 >>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>К сожалению, между исключениями, порождаемыми разнами провайдерами, практически нет ничего общего. Следовательно, всё что можно сделать — это выбрать из такого исключения сообщение и само сообщение сохранить как вложенное. Пользователю всё равно придётся самостоятельно всё это обрабатывать, чтобы добраться до сути. Поэтому, особого смысла изобретать рапер и всё усложнять нет.
Пользователя программы что должно интересовать? Что операция была окончена неудачно. А также возможность отослать разработчику информацию об ошибке. Разработчика что должно интересовать? Возможность получить исчерпывающую информацию об ошибке.
То, что исключения от разных провайдеров очень разные, роли не играет никакой.
try
{
... получение дата ридера
... а также всякие операции с ним
}
catch(Exception e)
{
new ExceptionHandler(e);
}
а внутри класса ExceptionHandler сделайте обработку всех исключений, выдачу понятного пользователю сообщения и создание лога с исчерпывающей информацией. Внутри этого класса в лог скиньте StackTrace обработанный, сообщение об ошибке, ещё если надо что.. Программисту который использует Ваш класс, будет этого достаточно.