45810 (665154), страница 3
Текст из файла (страница 3)
Чтение данных с использованием DbObjectReader
В отдельных случаях использование класса ObjectSpace может оказаться избыточным или неудобным. Например, если для доступа к базе данных необходимо использовать хранимые процедуры, большая часть функциональности ObjectSpaces окажется ненужной. Но и для подобных ситуаций в ObjectSpaces есть свое решение. Если требуется извлекать из произвольного источника данных информацию в виде объектов приложения, можно использовать класс DbObjectReader. Выступая как тонкая прослойка между ADO.NET-курсором (IDataReader) и классами приложения, DbObjectReader позволяет загружать сохраняемые объекты из источников данных, которые не поддерживаются ObjectSpaces напрямую.
public static void Main() { DataTable table = new DataTable(); table.Columns.Add("CustomerID", typeof(int)); table.Columns.Add("CompanyName", typeof(string)); table.Columns.Add("ContactName", typeof(string)); table.Columns.Add("Phone", typeof(string)); table.Rows.Add(new object[] { 1, "MyCompany", "MyCustomer", "222 33 22" }); using (IDataReader reader = table.GetDataReader()) { DbObjectReader objectReader = new DbObjectReader(reader, typeof(Customer), new MappingSchema("map.xml")); while (objectReader.Read()) { Customer cust = (Customer)objectReader.Current; Console.WriteLine(cust.Name); } } } |
ObjectEngine
Класс ObjectEngine лежит в основе ObjectSpaces и реализует механизмы взаимодействия с источником данных. В большинстве случаев ObjectEngine напрямую не используется, но в ситуациях, когда необходимо выполнить OPath-запрос или сохранить объект в БД в обход основной функциональности ObjectSpaces и с минимальными издержками – использование ObjectEngine может пригодиться.
// Небольшой пример использования функциональности ObjectEngine public static void Main() { using (SqlConnection conn = new SqlConnection( "Data Source=tim; Integrated Security=SSPI; Database=northwind")) { conn.Open(); // Учитывая, что ObjectEngine – это “низкоуровневый” класс, некоторую часть // подготовительной работы приходится выполнять самостоятельно. ObjectContext context = new CommonObjectContext(new ObjectSchema("osd.xml")); MappingSchema msd = new MappingSchema("map.xml"); ObjectSchema osd = new ObjectSchema("osd.xml"); ObjectSources sources = new ObjectSources(); sources.Add("NorthwindRSD", conn); // Создаем OPath запрос и читаем данные из БД ObjectExpression expr = OPath.Parse( new ObjectQuery(typeof(Customer), "", ""), osd); // Еще одна издержка ObjectEngine – перед использованием OPath // запрос надо “компилировать”. CompiledQuery query = expr.Compile(msd); Customer cust = null; // Выполняем OPath-запрос, используя “объектный” курсор. using (ObjectReader reader = ObjectEngine.GetObjectReader(sources, context, query, new object[] { })) { while (reader.Read()) { cust = (Customer)reader.Current; Console.WriteLine(cust.Name); } } // Cоздаем объект и сохраняем его в источнике данных cust = new Customer(); cust.CustomerID = "alfq"; cust.Name = "MyName"; cust.Phone = "MyPhone"; cust.Company = "MyComp"; context.Add(cust, ObjectState.Inserted); ObjectEngine.PersistChanges(msd, sources, context, new object[] { cust }, PersistenceOptions.Default); } } |
Расширения ObjectSpaces
Использование нескольких XML-схем для описания структуры классов приложения, реляционной структуры БД, а кроме того еще и Mapping-схемы, не может не удручать. Конечно, в финальной версии .NET Framework 1.2 возможности визуального проектирования этих схем должны обязательно появиться, но пока их нет, можно воспользоваться сторонними средствами. Одно из таких средств входит в пример ObjectSpacesPDCSamples.zip (файл можно найти на http://www.gotdotnet.com).
В состав этого примера входит специальная утилита для создания всех необходимых XML-схем (рисунок 4).
Рисунок 4. Microsoft ObjectSpaces Mapper Utility.
Кроме этого, в данный пример входит реализация класса ObjectPersistence. Этот класс обладает одной характерной особенностью – он скрывает в себе не только создание XML-описаний, но и создание необходимой базы данных. Рассмотрим простейший пример использования ObjectPersistence.
using System; using Microsoft.ObjectSpaces.ObjectPersistence; class ObjectPersistenceDemo { // Исходный код класса ObjectPersistence также доступен в рамках примера static ObjectPersistence op = new ObjectPersistence("Data Source=local; Integrated Security=true;", "Persistence"); static void Main(string[] args) { Customer c = new Customer(); // Ищем заказчика в базе данных c = (Customer)op.LoadObject(typeof(Customer), "CustomerID = 'alfki'"); if (c == null) { c = new Customer("alfki"); c.Comments = "New Customer"; } else { c.Comments = "Old Customer"; } // Сохраняем изменения. // Если база данных/таблица еще не созданы, то это произойдет сейчас op.Persist(c); } } |
Класс ObjectPersistence спроектирован таким образом, что для его использования не обязательно предварительно создавать базу данных, настраивать XML-схемы данных – все это делается внутри реализации ObjectPersistence. Так, в приведенном выше примере на SQL Server будет создана база данных Persistence, и в нее будет добавлена таблица с именем Customer. Конечно, не в каждом проекте можно допустить подобные вольности со стороны библиотеки доступа к данным, но для простейших реализаций – это замечательная возможность скрыть ненужные детали.
Итог
Технологии доступа к данным в .NET Framework 1.2 содержат множество полезных нововведений, но если для ADO.NET это скорее эволюционные изменения, связанные с простым расширением библиотеки, то ObjectSpaces является совершенно новым продуктом, который может кардинальным образом изменить подход к работе с данными. Конечно, в настоящий момент работа над библиотекой еще далека от завершения. К моменту выхода VisualStudio «Whidbey» мы сможем увидеть в ней массу изменений, начиная с использования generics и расширения возможностей OPath, и заканчивая DML-операторами для удаления объектов без предварительного их извлечения.
Список литературы
Для подготовки данной работы были использованы материалы с сайта http://www.rsdn.ru/