Реферат по предмету "Программирование"


Введение в ObjectSpaces

Введение в ObjectSpaces

Тимофей Казаков (TK)
Сохраняемые объекты


В .NET Framework управление данными осуществляется на
уровне объектов. Каждый объект характеризуется своим состоянием (свойства), поведением
(методы), и является экземпляром какого-либо конкретного класса. В рамках
приложения классы могут различаться по целевому назначению – это могут быть
элементы управления, отображающие интерфейс пользователя, или сервисные классы,
отвечающие за связи с базами данных и работу с сетевыми функциями, это могут
быть классы “сообщений”, обеспечивающие обмен информацией между частями
приложения. Все эти сущности объединяет одна общая черта – время их жизни
обычно не превышает времени жизни всего приложения. Но, кроме вышеперечисленных
категорий классов, можно выделить целый ряд сущностей, время жизни которых
превышает срок жизни приложения. Например, в бизнес-задачах роль подобных
сущностей могут играть объекты “Клиент”, “Заказчик”, “Продукт”. Таким объектам
необходимо предоставить возможность сохранения своего состояния во внешнее
хранилище.

В .NET Framework существуют готовые средства для
работы с сохраняемыми объектами, – есть возможность сохранять состояние
объектов в двоичном виде с использованием BinaryFormatter или XML-формате с
использованием XmlSerializer. Все эти средства предоставляют возможности
сохранения “графов” объектов, однако сохраняемая информация не оптимизирована
для выполнения запросов к хранимым данным – так, поиск необходимой информации в
XML-файле, содержащем несколько тысяч записей, может оказаться неприемлемо
медленным. В большинстве подобных случаев в качестве хранилища информации
подойдет реляционная СУБД – данные сохраняются в таблицах, для дополнительного
контроля целостности между ними устанавливаются отношения, поиск информации
осуществляется с использованием языка запросов SQL. Аналогичную
функциональность предоставляют специальные библиотеки Object/Relational Mapping
(O/R Mapping). Такая библиотека перекладывает на себя всю “черную” работу по
сохранению/загрузке информации из объектной модели приложения в реляционную
модель базы данных. В .NET Framework 1.2 для этих целей есть специальный набор
классов из пространства имен System.ObjectSpaces.*.
ObjectSpaces


Если раньше, используя ADO.NET, нужно было
самостоятельно писать SQL-запросы, то теперь это требование становится
необязательным – ObjectSpaces берут на себя всю заботу об отображении классов
приложения на различные источники данных. При этом мы можем создавать новые объекты,
сохранять их, выполнять различные запросы - все необходимые действия по
взаимодействию с источником данных будут выполняться внутри ObjectSpaces (при
этом данные могут находиться как в традиционной БД, так и быть представленными
в XML форме)




ПРЕДУПРЕЖДЕНИЕ


Текущая версия ObjectSpaces
поддерживает в качестве источника данных только SQL Server 7.0 и выше.






Для объектов приложения ObjectSpaces предоставляет
следующие возможности:

Прозрачное отображение экземпляров .NET объектов на
источник данных.

Поддержку иерархий классов для сохраняемых объектов.

Сохранение взаимосвязей между объектами (один к
одному, один ко многим, многие ко многим).

Отложенную загрузку связанных объектов. Построение
запросов с использованием OPath.
Архитектура ObjectSpaces


Какая функциональность требуется от O/R
Mapping-библиотеки? Кроме очевидных задач – загрузки/сохранения состояния
объекта и выполнения операций поиска, есть и менее очевидные задачи –
отслеживание состояния и идентификация объекта. Для чего это нужно?

Отслеживание состояния требуется для принятия решения
о необходимости сохранения объекта. Совершенно очевидно, что если ни одно из
полей объекта не изменялось, то повторно сохранять ту же информацию совершенно
не обязательно. Информация об оригинальных значениях полей может понадобиться и
для достижения “оптимистической параллельности” (optimistic concurrency) в
ситуациях, когда в БД нет колонки с версией записи. Также можно оптимизировать
сохранение полей объекта для ситуаций, когда один объект отображается на
несколько таблиц в базе данных, просто не обновляя не изменившиеся данные.




ПРИМЕЧАНИЕ


Optimistic concurrency (оптимистический
параллелизм) – это возможность двум независимым клиентам редактировать одну и
ту же информацию без дополнительной блокировки каких-либо ресурсов. Все
проверки относительно правомочности сделанных изменений осуществляются только
в момент сохранения записи. Это можно реализовать, например, добавлением в
таблицу специального поля для идентификации версии записи (например, timestamp).






В каких случаях нужно уметь идентифицировать объект? В
случае с O/R Mapping-библиотекой мы работаем не с “сырыми” данными, а с
реальными объектами. Это значит, что одному значению первичного ключа в базе
данных должен соответствовать один объект в приложении. В самом деле, разумно
рассчитывать, что все возможные способы получения одного и того же объекта из
базы данных каждый раз должны возвращать одну и ту же ссылку. Это означает, что
O/R Mapping-библиотека должна отслеживать все загружаемые объекты, и в случае
повторной попытки восстановить объект с тем же значением первичного ключа
возвращать ссылку на уже загруженный.

Какие есть пути для реализации подобной
функциональности? Реализация функциональности идентификации объектов
пересекается с реализацией отслеживания состояния объекта и не представляет
особой сложности. Поэтому сосредоточимся на том, какими способами можно
обеспечить отслеживание состояния.

Есть два варианта отслеживания состояния объекта. В
первом варианте инициатором сохранения состояния выступает сам объект. По
второму варианту объект играет пассивную роль, а вся необходимая
функциональность реализуется в библиотеке O/R Mapper. Разберем каждую из двух
реализаций более подробно.

Инициатором сохранения выступает объект. В данной
ситуации O/R Mapper предоставляет механизм хранения оригинальных и текущих
значений, а “сохраняемый” объект выступает лишь интерфейсом для работы c этим
хранилищем. Здесь можно выделить два возможных направления:

“Сохраняемый” класс описывается на некотором метаязыке.
Что это за метаязык, и какие средства работы с ним используются, в общем случае
не столь важно. Отличительной особенностью данной реализации является то, что
весь необходимый код отслеживания состояния генерируется на этапе разработки
(компиляции). В качестве примера подобного подхода можно взять реализацию
Borland Enterprise Core Objects (ECO).

Все свойства, для которых необходимо предоставить
возможности “сохранения” объявляются как абстрактные, сам такой класс также
становится абстрактным (MustInherit в VisualBasic). На O/R Mapping-библиотеку в
такой ситуации ложится ответственность за создание наследника “сохраняемого”
(например, через Reflection.Emit) класса с неизбежной реализацией всех
сохраняемых свойств, и предоставление фабрики класса для его создания. Найти
реализацию подобной функциональности можно в ранней preview-версии ObjectSpaces
и в EntityBroker (http://www.thona-consulting.com).

У каждого из этих направлений есть свои достоинства и
недостатки. Плюсом первого направления является более быстрый запуск, т.к. весь
необходимый код сгенерирован еще на этапе компиляции. Между тем, этот плюс
может стать и минусом – если по какой-то причине реализация “отслеживания”
состояния изменится, придется повторить операцию генерации кода сохраняемого
класса и перекомпилировать его. В случае использования второго направления
будет достаточно заменить реализацию O/R Mapper.

Объект играет пассивную роль, вся реализация – в O/R
Mapper. В этой ситуации к “сохраняемому” классу не предъявляется никаких
дополнительных требований. Основной плюс данного подхода состоит в том, что для
добавления “сохраняемости” к существующему классу его не надо никак
модифицировать (максимальная прозрачность в использовании O/R Mapper), а минус
состоит в том, что для сохранения закрытых полей класса приходится использовать
механизмы рефлексии, что может отрицательно сказаться на производительности.

В ObjectSpaces выбран второй вариант. В основе
реализации ObjectSpaces (Рисунок 1) лежат три основных класса: ObjectEngine,
ObjectContext и ObjectSpace.

ObjectEngine (его использование более подробно
рассматривается ниже) отвечает за низкоуровневое взаимодействие с источником
данных.

ObjectContext – это реализация механизмов
идентификации и отслеживания состояния “сохраняемых” классов.

ObjectSpace. Класс ObjectSpace на более высоком уровне
объединяет функциональность, заложенную в реализациях ObjectEngine и
ObjectContext. Для отображения реляционной модели данных в объектную
ObjectSpace использует набор XML-схем, описываемых классом MappingSchema.



Рисунок 1 Архитектура ObjectSpaces.

Схемы данных


Для большинства приложений описать однозначное (“один
к одному”) отображение объектной модели данных на реляционную модель нельзя,
иногда нужно специально описывать то, как объекты должны отображаться на
источник данных. В ObjectSpaces эту задачу выполняет класс MappingSchema
(пространство имен System.Data.Mapping). Данный класс предназначен для
описания:

RSD (Relational Schema Definition) – схемы, которая
описывает таблицы, поля и отношения между ними;

OSD (Object Schema
Definition) – схемы, описывающей объекты;

MSD (Mapping Schema
Definition) – схемы отображения.

ObjectSpaces дает возможность самостоятельно
формировать состояние класса MappingSchema или загружать его состояние из
XML-файла. Рассмотрим использование MappingSchema на основе базы данных
Northwind из состава SQL Server. На первом этапе нужно описать структуру этой
базы данных в RSD-схеме:







 xmlns:rsd="http://schemas.microsoft.com/data/2002/09/28/rsd">


 


 


  


   


    


          
IncrementStep="1" IncrementSeed="1"/>


    


          
Precision="5"/>


    


    


    


    


    


     
0


    


   


   


    


     


    


    


     


    


   


  


  


   


    


    


    


          
SqlType="nvarchar" Precision="30"/>


    


           Precision="24"/>


   


   


    


     


    


   


  


 


 









Эта схема описывает две таблицы из базы данных
Northwind (рисунок 2). Для таблиц Customers и Orders описываются исходные поля
в БД, первичные ключи, а также связи между таблицами.



Рисунок 2. ER-диаграмма

Кроме этого, понадобится описать OSD-схему, которая
будет описывать объекты C#-кода.







 xmlns:osd="http://schemas.microsoft.com/data/2002/09/20/persistenceschema">


 


 


  


  


  


  


  


 


 


  


        
Hidden="false" Key="true"
Alias="OrderID" />


  


  


  


  


  


  


 


 


 


 


     Type="OneToMany"
ParentClass="Rsdn.Samples.Northwind.Customer"


    
ParentMember="Orders"
ChildClass="Rsdn.Samples.Northwind.Order"


    
ChildMember="Customer" />


 











Рисунок 3. Объектная модель.

После объявления RSD- и OSD-схем (рисунок 3), нужно
создать Mapping-схему, которая определит отображение одной схемы на другую:







 


 


  


  


  


  


          
FromVariable="Customers" ToVariable="Orders">


   


  


 


 


  


 


 


 


 


      TargetSelect="Rsdn.Samples.Northwind.Customer">


  


  


  


  


 


 


     
TargetSelect="Rsdn.Samples.Northwind.Order">


  


  


   


  


  


        
TargetField="EmployeeID" NullValue="-1" />


  


 


 


 









OPath


Одна из основных задач при работе с информацией – это
создание запросов для выборки необходимых данных. Так, в случае РСУБД можно
использовать язык запросов SQL, для выборки информации из XML-источников у нас
есть XPath. Но как SQL, так и XPath – это языки запросов, которые слишком
сильно привязаны к модели хранения данных и, как результат, для O/R Mapper
приходится применять специальный язык запросов, который позволит создавать
запросы к данным в терминах объектной модели приложения и легко транслировать
их в язык, понимаемый хранилищем данных (для ObjectSpaces и MS SQL Server это
SQL).

Для обращения к источнику данных в ObjectSpaces
используется специальный язык запросов – OPath. Синтаксис этого языка
(отдаленно он напоминает XPath) позволяет выполнять запросы к источнику данных,
основываясь на иерархии классов, используемых в приложении. В настоящее время
OPath поддерживает следующий набор операторов (для операторов может
использоваться синтаксис как C#, так и VB.NET):




Оператор в C# стиле





Оператор в VB стиле





Описание







.


[]





.


()





Операторы группировки
используются для разделения свойств и группировки выражений.
Например:Customer[CustomerID=’alfki’].Orders.ShipDate>#11/12/2003#







!





not





Логическое отрицание. not (Customer[CustomerID=’alfki’])







*


/


%





*


/


MOD





Умножение, деление,
получение модуля







+


-





+


-





Сложение, вычитание










>





>=








>





>=





Сравнение двух
значенийCustomer.CreateDate > #12/09/2002#







=


!=


==





=





==





Равенство двух значений







&&


||





and


or





Customer.Region = ‘ru’ || Customer.Region = ‘en’







^





^





Символ ^ используется для
обозначений родитель/потомок. В случае использования оператора ^ следующие
два выражения эквивалентны:Orders.OrderDetail[^.OrderDate >
#1/1/2003#]Orders.[OrderDate > #1/1/2003#]






ObjectSpace


При работе с сохраняемыми объектами нам нужны
следующие возможности – загрузка сохраненных объектов, отслеживание состояния и
возврат изменений обратно, в базу данных. Класс ObjectSpace объединяет в себе
все эти возможности. Рассмотрим отдельные моменты работы с этим классом.

Создание экземпляра ObjectSpace

Для создания экземпляра ObjectSpace нужно иметь три
схемы – RSD, OSD и MSD (при желании их можно скомбинировать в одном XML-файле),
а также экземпляр SqlConnection для взаимодействия с источником данных.




// Создание экземпляра класса ObjectSpaces


using (SqlConnection conn = new SqlConnection(


 "Data Source=tim;
Integrated Security=SSPI; Database=northwind"))


{


 ObjectSpace os = new
ObjectSpace("map.xml", conn);



 // Работаем с os. Явно открывать подключение SqlConnection не
обязательно.


 // Это происходит автоматически.


}






Запрос к источнику данных

После инициализации экземпляра ObjectSpace можно
обратиться к источнику данных. Для этого у класса ObjectSpace есть три метода
GetObject, GetObjectReader, GetObjectSet которые позволяют получать данные в
виде трех различных форм – одиночный объект, курсор или список.




 // Определим “сохраняемые” объекты, которые
будем использовать в дальнейшем


 public class Customer


 {


  public string CustomerID;


  public string Name;


  public string Company;


  public string Phone;


  public string Fax;


  public ArrayList Orders = new
ArrayList();


 }



 public class Order


 {


  private int _orderID = 0;



  public int OrderID


  {


   get { return _orderID; }


  }



  public DateTime OrderDate;


  public DateTime RequiredDate;


  public DateTime ShippedDate;


  public Decimal Freight;


  public int EmployeeID;


  public Customer Customer;


}



// Извлекаем объект
Customer (включая подчиненное свойство Orders)


// на основе OPath-запроса (City='Berlin'
&& Orders.OrderDate


// Для каждого экземпляра
класса Customer загружается свойство “Orders”.


Customer cust = (Customer)os.GetObject(typeof(Customer),


   "City='Berlin'
&& Orders.OrderDate






Во что выливается вызов приведенного выше метода
os.GetObject? Используя Profiler из MS SQL Server, можно увидеть, что в БД
будет выполнен следующий SQL-запрос (отформатирован для приведения в более
“читаемый” вид):




exec sp_executesql


N'select Customers.[CustomerID],


   Customers.[CompanyName],


   Customers.[ContactName],


   Customers.[City],


   Customers.[Phone]


  from
[Northwind].[dbo].[Customers] as Customers


  where ((Customers.[City]) =
(@p0))


    AND (EXISTS(


       select Orders.[OrderID],
Orders.[CustomerID]


        from
[Northwind].[dbo].[Orders] as Orders


        where ((Customers.[CustomerID])
= (Orders.[CustomerID]))


         AND
((Orders.[OrderDate]) > (@p1))))


 order by 1;



select Customers.[CustomerID],


  Orders.[OrderID],


  Orders.[CustomerID],


  Orders.[RequiredDate],


  Orders.[ShippedDate],


  Orders.[OrderDate]


 from
[Northwind].[dbo].[Customers] as Customers,


    [Northwind].[dbo].[Orders]
as Orders


 where (((Customers.[City]) =
(@p0))


  AND (EXISTS(


   select Orders.[OrderID],
Orders.[CustomerID]


    from
[Northwind].[dbo].[Orders] as Orders


    where
((Customers.[CustomerID]) = (Orders.[CustomerID]))


     AND
((Orders.[OrderDate])>(@p1)) )))


     AND
((Customers.[CustomerID])=(Orders.[CustomerID]))


 order by 1, 2, 3 ;',



N'@p0 nvarchar(6),@p1 datetime', @p0 = N'Berlin',


 @p1 = 'Oct 10 1998 12:00:00:000AM'






Создание записей в базе данных

Одно из больших преимуществ в использовании
ObjectSpaces состоит в том, что для добавления объекту свойств “сохраняемости”
его не надо специальным образом модифицировать (наследовать от специального базового
класса, специальным образом размечать свойства или поля). Подобная прозрачность
реализации ObjectSpaces дает преимущества в использовании.




// Работа с объектами
Customer и Orders не зависит


// от того, используется
ObjectSpaces или нет


Customer cust = new Customer();


Order ord = new Order();



cust.Id = "ALFQI";


cust.Name = "MyName";


cust.Company = "MyCompany";


cust.Phone = "MyPhone";


cust.Fax = "MyFax";



ord.Customer = cust;


ord.OrderDate = DateTime.Now;


ord.ShippedDate = DateTime.Now;


ord.RequiredDate = DateTime.Now;


cust.Orders.Add(ord);



// Перед сохранением
объектов необходимо поместить их в контекст


// ObjectSpaces. Флаг
InitialState.Inserted показывает, что мы добавляем новую


// запись в базу данных


os.StartTracking(ord, InitialState.Inserted);


os.StartTracking(cust, InitialState.Inserted);



// Сохраняем экземпляр класса Customer.


// Параметр
PersistenceOptions(Depth.ObjectGraph) сообщает,


// что будет сохранен весь
граф объектов.


os.PersistChanges(cust, new PersistenceOptions(Depth.ObjectGraph));






Удаление записей с использованием ObjectSpaces

Существующая версия ObjectSpaces поддерживает удаление
объектов только в том случае, если они ранее были добавлены в контекст
ObjectSpaces.




ПРИМЕЧАНИЕ


Для удаления объекта из базы данных его
необходимо предварительно добавить в контекст ObjectSpaces. Это можно
сделать, используя методы GetObject, GetObjectReader, GetObjectSet класса
ObjectSpace, или добавить объект в контекст самостоятельно с помощью метода
StartTracking









Customer
cust = new Customer();


cust.Id
= "ALFQI";



// Перед операцией над объектом
необходимо поместить его в контекст


// ObjectSpaces. Флаг
InitialState.Unchanged показывает, что объект ранее


// был сохранен в базе данных


os.StartTracking(cust,
InitialState.Unchanged);



// Помечаем экземпляр класса Customer
как удаляемый.


os.MarkForDeletion(cust);



// Сохраняем изменения в базе данных


os.PersistChanges(cust);






Отложенная загрузка данных

Отложенная загрузка данных – это очень полезная
возможность, реализованная в ObjectSpaces. Правда, использование этой
функциональности омрачается ее недостаточной “прозрачностью”. Это значит, что в
случае, когда необходимо подгружать зависимые классы по требованию, придется
модифицировать исходный код. К счастью, модификации незначительны.




public class Customer


{


 public string CustomerID;


 public string Name;


 public string Company;


 public string Phone;


 public string Fax;



 // Для отложенной загрузки списка заказов необходимо перейти


 // от использования ArrayList к
использованию специального класса из


 // ObjectSpaces – ObjectList.


 public ObjectList Orders = new
ObjectList();


}



public class Order


{


 private int _orderID = 0;



 public int OrderID


 {


  get {return _orderID;}


 }



 public DateTime OrderDate;


 public DateTime RequiredDate;


 public DateTime ShippedDate;


 public Decimal Freight;


 public int EmployeeID;



 // Для отложенной загрузки класса Customer, мы меняем тип поля с Customer


 // на ObjectHolder. Именно ObjectHolder будет отвечать за подгрузку
нужных


 // данных.


 private ObjectHolder _customer
= new ObjectHolder();



 public Customer Customer


 {


  get {return (Customer)
_customer.InnerObject;}


  set {_customer.InnerObject = value;}


 }


}






Кроме изменения кода приложения, отложенную загрузку
свойств следует объявить в OSD-схеме. Для этого нужно добавить в описание полей
специальный атрибут LazyLoad=”true”.










 


 


 


 


 








 


       Hidden="false"
Key="true" Alias="OrderID" />


 


 


 


 


 


 









После этого можно работать с восстановленным объектом
как обычно:




using (SqlConnection conn = new SqlConnection(


 "Data Source=tim;
Integrated Security=SSPI; Database=northwind"))


{


 ObjectSpace os = new ObjectSpace("map.xml",
conn);



 Customer cust =
(Customer)os.GetObject(typeof(Customer),


  "CustomerID=’alfki’");



 // Список заказов загрузится при первом
обращении


 foreach (Order order in cust.Orders)


 {


  Console.WriteLine(“Customer:
{0}, OrderDate: {1}”,


   order.Customer.Name,
order.OrderDate);


 }


}







Метод





Описание







BeginTransaction, Commit,
Rollback





Управление транзакциями.
Стоит обратить внимание, что метод Rollback не откатывает изменения в
сохраняемых объектах, поэтому возможны ситуации, когда информация в БД и
информация в сохраняемых объектах окажутся несогласоваными. Поэтому, во
избежание конфликтов, рекомендуется после Rollback создавать новый экземпляр
ObjectSpaces.







GetObject





Получить одиночный объект
заданного типа из базы данных. В параметрах метода можно передать как
OPath-запрос, так и список дочерних объектов, которые должны быть загружены
одновременно с запрашиваемым объектом.







GetObjectReader





Получить из базы данных
объекты через курсор, используя семантику, аналогичную используемой при работе
с IDataReader.







GetObjectSet





Получить объекты из БД в
виде единого массива. В отличии от ArrayList, класс ObjectSet предоставляет
дополнительные возможности отслеживания оригинальных значений, передачи
изменений через Remoting и некоторые другие.







PersistChanges





Сохранить измененный объект
в БД.







MarkForDeletion





Пометить объект для
удаления. Реальное удаление происходит при вызове PersistChanges.







Resync





Синхронизировать состочние
объекта с информацией из БД.







StartTracking





“Пометить” объект как сохраняемый.
Кроме текущих значений, в контексте сохраняется и состояние объекта
(новый/измененный/удаленный/без изменений)







Дополнительные возможности ObjectSpaces


Чтение данных с использованием 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/


Не сдавайте скачаную работу преподавателю!
Данный реферат Вы можете использовать для подготовки курсовых проектов.

Поделись с друзьями, за репост + 100 мильонов к студенческой карме :

Пишем реферат самостоятельно:
! Как писать рефераты
Практические рекомендации по написанию студенческих рефератов.
! План реферата Краткий список разделов, отражающий структура и порядок работы над будующим рефератом.
! Введение реферата Вводная часть работы, в которой отражается цель и обозначается список задач.
! Заключение реферата В заключении подводятся итоги, описывается была ли достигнута поставленная цель, каковы результаты.
! Оформление рефератов Методические рекомендации по грамотному оформлению работы по ГОСТ.

Читайте также:
Виды рефератов Какими бывают рефераты по своему назначению и структуре.