Vvmebel.com

Новости с мира ПК
2 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Data access layer

Работа с данными в ASP.NET. Создание DAL (Data Access Layer)

За основу для данной статьи, я взял статью «Creating a Data Access Layer» ( http://www.asp.net/learn/data-access/tutorial-01-cs.aspx )

Я её попытался перевести, так как знания английского у меня не на самом хорошем уровне, но главное я понял как ОНО работает и попытаюсь об этом поведать вам. Буду придерживаться плана оригинальной статьи, но стиль написания местами поменяю.

Введение

В задачи каждого web -разработчика входит работа с данными. Можно даже смело заявить, что это первостепенная задача программиста. Мы создаем базы данных для хранения информации, мы пишем скрипты и запросы для её грамотного извлечения, изменения или добавления, мы создаем сайты для её представления.

Эта статья первая в своей серии «Работа с данными в ASP . NET «, в которой я буду описывать различные техники работы с данными в ASP . NET . В данной статье я опишу процесс создания приложения, использующего Typed DataSets .

Для изучения материала данной статьи вам необходимо иметь Microsoft SQL Server 2005 Express Edition или выше и базу данных Northwind , которую вы можете скачать с сайта Microsoft ( http :// www . microsoft . com / downloads / detail . aspx ? FamilyId =06616212-0356-46 A 0-8 DA 2- EEBC 53 A 68034& displaylang = en ), также вам необходимо иметь на своем компьютере Microsoft Visual Studio , или хотя бы Microsoft Visual Web Developer Express (можно найти на сайте Microsoft ) версии 2005 или 2008 (может и выше, по крайней мере на момент написания этой статьи у меня стоит Visual Web Developer Express 2008)

Если у вас есть все необходимое, то наберитесь терпения и. Поехали!

Первый шаг. Создание проекта и подключение к базе данных

Для того, чтобы нам создать наш Data Access Layer ( DAL ), нам необходимо создать проект в Visual Studio (или Visual Web Developer Express , здесь и далее просто VS ). Для этого, откройте программу, перейдите в меню » File » и выберите пункт » New Web Site …». Укажите шаблон » ASP . NET Web Site «, » Location : File System » и выберите произвольный путь, или если у вас установлен и настроен IIS , то » HTTP » (лично я делал вторым способом, как установить и настроить IIS я расскажу в другой раз, воспользуйтесь http :// www . google . com / ), и укажите используемый язык в C # (» Language : C #»).

Рисунок SEQ Рисунок * ARABIC 1. Создание ASP . NET приложения

После нажатия на кнопку » OK «, VS автоматически создаст проект, содержащий стартовую страницу Default . aspx и директорию App _ Data .

Теперь, когда сайт создан нам необходимо добавить к нему базу данных Northwind с помощью Server Explorer в VS . С помощью Server Explorer вы можете совершать манипуляции с базой данных, например, создавать, изменять или удалять таблицы, хранимые процедуры, представления и все это прямо в VS . Вы также можете просмотреть содержимое таблиц и создать собственные запросы, в том числе в графическом режиме, используя Query Builder .

При создании TypedDataSet нам будет необходимо показать VS базу данных, по образу которой будет построен наш Typed DataSet .

Добавление базы данных к проекту и подключение к ней

Во введении я говорил, что для проекта нам необходима база данных Northwind , если вы еще её не скачали её или не установили, сделайте это сейчас.

Для того, чтобы добавить базу данных в проект, откройте Solution Explorer (все указанные меню и утилиты находятся в меню » View «). Кликните правой кнопкой мыши по папке » App _ Data » и выберите пункт » Add Existing Item …», в появившемся диалоговом окне укажите файл » NORTHWIND . MDF «, у меня он лежал в директории «C:SQL Server 2000 Sample Databases».

Теперь откройте Server Explorer , в разделе Data Connections должна появиться база данных Northwind , если этого не произошло, то нажмите правой кнопкой мыши на пункте » Data Connecions » и выберите » Add Connection «, в появившемся окне смените Data Source на » Microsoft SQL Server Database File ( SqlClient )» и укажите местонахождение файла NORTHWIND . MDF . Нажмите » OK «.

Теперь у вас наверняка должна появиться база данных Northwind в списке Data Connections . Теперь вы можете посмотреть содержимое базы данных, таблиц, выполнить запросы и прочая, и прочая.

Рисунок SEQ Рисунок * ARABIC 2. База данных в Server Explorer

Второй шаг. Создание Data Access Layer

Для начала разберемся, что же такое Data Access Layer . Любое приложение, которое работает с данными, включает в себя так называемый уровень представления , в web -приложениях это страницы, которые показывают эти данные. Естественно, что для того, чтобы данные можно было представить, в прложении должна быть реализована логика обработки данных. В ASP . NET это может быть реализовано с помощью написания кода ADO . NET в страницах или использования элемента управления SqlDataSource или еще каким либо образом. В любом случае приложение будет содержать в себе логику доступа к данным . Рекомендуется логику доступа к данным вынести из уровня представления в отдельный — уровень доступа к данным , Data Access Layer ( DAL ). Все выгоды такого подхода очень хорошо описаны, в конце статьи я укажу ссылки на другие статьи, описывающие эти выгоды.

Любой код, который осуществляет обработку данных, их выборку, изменение, команды SELECT , INSERT , UPDATE , и DELETE и прочие, должен находиться в DAL . Уровень представления не должен содержать в себе никакого кода обращения к базе данных, все данные в нем должны браться из DAL . База данных Northwind , взятая в качестве примера, содержит в себе такие таблицы, как Products и Categories , в которых хранится информация о товарах и о категориях, к которым они принадлежат. В нашем DAL мы должны описать следующие методы:

· GetCategories (), который выдаст информацию обо всех существующих в базе данных категориях

· GetProducts (), который выдаст информацию обо все существующих товарах

· GetProductsByCategoryID ( categoryID ), который выдаст информацию обо всех продуктах, принадлежащих определенной категории

· GetProductByProductID ( productID ), который выдаст информацию об определенном товаре

Указанные методы выполнят подключение к базе данных, выполнят запрос и вернут полученный результат. То, в каком виде они вернут результат является очень важным! Эти методы могут вернуть стандартный DataSet или DataReader , заполненный данными из таблицы, но лучше будет, если они вернут strongly-typed objects (Если честно, не знаю как это переводится). A strongly-typed object is one whose schema is rigidly defined at compile time, whereas the opposite, a loosely-typed object, is one whose schema is not known until runtime.

Например, DataReader или DataSet (используемый по умолчанию) имеют очень грубую структуру, т.к. она уже определена и при выполнении запроса такой объект просто заполняется результатом. Предположим мы имеем DataSet , в котором содержится результат какого-либо запроса. Для того чтобы этот результат получить мы должны обратится к нему кодом, вида DataTable . Rows [ index ][» ColumnName «] . Причем результат всегда имеет тип object . При обращении к нему мы должны использовать строковые и числовые «координаты». В другом же случае, таблица данных будет представлена в качестве объекта класса, где все столбцы таблицы будут определены как свойства класса, причем того же типа, в каком они определены в базе данных, а обращение примет вид DataTable . Rows [ index ]. ColumnName .

Для того, чтобы получать результаты в виде strongly-typed objects можно определить свой класс, в котором свойства будут отражать столбцы таблицы, а можно использовать Typed DataSet , который VS сделает сама.

В данной статье мы будем использовать Typed DataSet .

На следующем рисунке изображено взаимодействие между различными уровнями приложения при использовании Typed DataSet .

Рисунок SEQ Рисунок * ARABIC 3. Весь код по выборке и обработке данных возложен на DAL

Создание Typed DataSet и DataTable Adapter

Для того, чтобы создать наш собственный Typed DataSet , необходимо добавить его к проекту. Для этого кликните правой кнопкой мыши в ветке проекта в Solution Explorer и выберите » Add New Item …», в списке шаблонов выберите DataSet , и назовите его Northwind . xsd

В открывшемся окне редактора щелкните правой кнопкой мыши в любом пустом месте и выберите Add / TableAdapter . Откроется мастер создания TableAdapter .

Здесь я опустил описание, что такое TableAdapter . Смотрите оригинал статьи или используйте поиск.

Перво-наперво вас попросят указать используемое подключение. Выберите NORTHWIN . MDF , если у вас его еще нет, тогда нажмите New Connection и создайте его.

Читать еще:  Фильтр отчета access

Теперь необходимо определить каким образом данные будут браться из базы и определить первый запрос на выборку данных. Укажите Use SQL statements

Теперь необходимо ввести сам запрос. Его можно ввести вручную или использовать утилиту Query Builder . Введем запрос на выборку всех товаров из таблицы Products :

В Query Builder «е это будет выглядеть так:

После создания запроса на выборку, мастер предложит нам сгенерировать запросы на добавление, удеаление, редактирование записей в таблице. Что ж, не будем ему в этом препятствовать.

И, напоследок, мастер предложит нам выбрать какие методы надо создавать и предложит ввести названия этих методов.

Таким образом мы создали TableAdapter для таблицы Products . Реализовали два метода: Fill (), который позволит заполнить DataTable , переданную в качестве параметра, и метод GetProducts (), который вернет DataTable () после выполнения. А на экране мы увидим следующее:

На данном этапе мы уже можем обратиться к объекту ProductTableAdapter , например таким кодом:

NorthwindTableAdapters.ProductsTableAdapter productsAdapter = new NorthwindTableAdapters.ProductsTableAdapter();
Northwind.ProductsDataTable products; products = productsAdapter.GetProducts();
foreach (Northwind.ProductsRow productRow in products) Response.Write(«Product: » + productRow.ProductName + «
«);

Как вы видите, в данном коде мы не написали не бита для обращения к базе данных, мы обращаемся толька к объекту DataTable , который нам любезно возвращает функция GetProducts (); причем мы эту DataTable можем использовать в качестве DataSource для, скажем, выпадающего списка.

Ну вот и пришла пора привести конкретный пример! Для этого создадим страницу ASP . NET и назовем её AllProducts . aspx

Data Access Layer

Универсальный англо-русский словарь . Академик.ру . 2011 .

Смотреть что такое «Data Access Layer» в других словарях:

Data access layer — A data access layer (DAL) is a layer of a computer program which provides simplified access to data stored in persistent storage of some kind, such as an entity relational database. For example, the DAL might return a reference to an object (in… … Wikipedia

Data link layer — The OSI model 7 Application layer 6 Presentation layer 5 Session layer 4 Transport layer 3 Network layer 2 … Wikipedia

Data Link Layer — The Data Link Layer is Layer 2 of the seven layer OSI model. It responds to service requests from the Network Layer and issues service requests to the Physical Layer.The Data Link Layer is the protocol layer which transfers data between adjacent… … Wikipedia

data-link layer — The second of seven layers of the OSI Reference Model for computer to computer communications. The datalink layer validates the integrity of the flow of data from one node to another by synchronizing blocks of data and controlling the flow of… … Dictionary of networking

Data access object — This article is about the data access object design pattern in object oriented software design. For the Microsoft library of the same name, see Data Access Objects. In computer software, a data access object (DAO) is an object that provides an… … Wikipedia

Data Access in Real Time — (DART) is a Real time operating system used by EMC Celerra. It is a modified UNIX Kernel with additional functionality. DART is an embedded, real time, operating system comprising a modified UNIX kernel and dedicated file server software that… … Wikipedia

Data Access Language — Data Access Language, or simply DAL, was a SQL like language parser released by Apple Computer in 1990 to provide unified client/server access to database management systems. It was known for poor performance and high costs, something Apple did… … Wikipedia

Data Access Manager — The Data Access Manager (DAM) was a database access API for the Mac OS, introduced in 1991 as an extension to System 7. Similar in concept to ODBC, DAM saw little use and was eventually dropped in the late 1990s. Only a handful of products ever… … Wikipedia

data access object — noun an object in programming that provides an abstract interface to some type of persistence mechanism, providing some specific operations without exposing details of the persistence layer … Wiktionary

Microsoft Data Access Components — MDAC redirects here. For other uses, see MDAC (disambiguation). MDAC (Microsoft Data Access Components) Microsoft Corporation s MDAC provides a uniform framework for accessing a variety of data sources on their Windows platform. Developer(s)… … Wikipedia

Data virtualization — describes the process of abstracting disparate data sources (databases, applications, file repositories, websites, data services vendors, etc.) through a single data access layer (which may be any of several data access mechanisms). This… … Wikipedia

Building Simple Data Access Layer Using JDBC

Here’s how to build a data access layer with JDBC, including data transfer, database creation, and connecting to a database.

Join the DZone community and get the full member experience.

The aim of this tutorial is to manage the access of a table in database from separate layer written in java, this layer usually called Data Access Layer (DAL)

The most benefit from DAL is that it simplifies database access operations through some method calls like insert() and find() rather than making connection and executing some queries

this layer instead handles all database related calls and queries inside it.

Database Creation

We want to create a simple table for users, we may create it using these fields

Data Transfer Object

this layer should contain a simple class called Data Transfer Object(DTO) this object is just a simple mapping to the table, every column in the table would be a member variable in the class.

our aim is to order this layer to create, modify, delete or search for an entity Using simple java objects rather than dealing with SQL statements and other database related commands.

We want to map this table to our java code, we can do so by creating a simple class(bean) that contains the same fields.

To make it more encapsulated we should declare all field variables as private and create acessors (Setters and Getters) in addition to constructors, one of them is default constructor.

To map fields correctly, we should consider the NULL value in database. The default value for java primitives is a value like 0 in the case of int so we should provide a new data type that can hold the null value. We can do so by using special type of objects called wrappers like Integer instead on int.

Our final class would be like that:

A good practice is to provide default empty constructor, a full constructor and a full constructor without the id parameter.

Connecting to Database

We can facilitate Connecting to database by making a central class for connecting to the database
in this class we would provide connection parameters like database JDBC URL, user name and password as final variables (It’d be better to get them from a properties or XML configuration file)
provide a method to return a Connection object or null if it failed to connect, or it may be better throw a runtime exception in that case

Also we can include a main method to test this connection the whole class would be like this:

Data Access Object

This DAO can do CRUD operations, it can Create, Retreive, Updata, Delete from our table.

The interface of our DAO should be like this:

Retreive User

The user can be retreived by any unique field like id or name or mail for example. In this method we’re searching for a user by his id. The first step is to create a connection from the connector class then execute the select statement to get the user whose id is 7 we may query using this statement:

Just there we made a dynamic statement that takes the id from method parameter

by executing this query we get a result set holding the user or null, we can check for that using the next() method in the Resultset. If returned true, we shall proceed to get user data from the Resultset using data getters. After we fill the user with all the data we return with it. If there is no user with this id or any other Exception happened(like invalid SQL Statement) this method would return null.

Читать еще:  Access union all

It’s more convenient to make a separate method to extract user data from result set as we’d use it in many methods.

The new method would throw SQLException and would be provate to limit access only inside the class:

Our method would be modified to use the new method:

Login Method

The login would be similar. We want to provide user ans pass instaed of id, this should affect parameter list and query statement. This method would return a valid user if the user name and password are correct, null otherwise as there are many parameters, it’s more useful to use PreparedStatement

Select All Method

This method would return all users, so we should return them in a convenient container like array, but as we can’t expect the returned rows count. It’s better to use a collection like Set or List:

Insert Method

The insert method would take a user as an argument and execute an SQL update statement using the PreparedStatement object.
The executeUpdate method returns number of affected rows, we expect to insert a single row thus means It should return 1, if so we return true, otherwise we return false

update method

the update method is similar to the insert one
the only change is the SQL statement

Delete method

The delete method would use a simple query like
DELETE FROM user WHERE id=7
sending this query with the id parameter would delete this record, returning 1 if it’s deleted successfully

Writing a Data Access Layer (DAL) for SQL Server

By: Arshad Ali | Updated: 2010-06-07 | Comments (8) | Related: More > Application Development
Problem

Almost every application being developed stores data in some form to make it persistent, this could be either storing it in file, Excel, XML format or in relational database. So each time, when you develop an application, you are required to write code for storing and retrieving data from these data sources.

In this tip, I am going to show you how you can create a Data Access Layer (to store, retrieve and manage data in relational database) in ADO .NET. I will show how you can make it data provider independent, so that you don’t have to re-write your data access layer if the data storage source changes and also you can reuse it in other applications that you develop.

Solution

ADO .NET provides several classes to work with a relational database, for example if you have your data in SQL Server you can use an instance of SqlConnection class to connect to the SQL Server. To execute a command you would create an instance of the SqlCommand class, assign appropriate properties and execute the command on the connection you created. Apart from these two important classes there are a couple of other classes as well, some of them I will be demonstrating in these examples.

In Code Block 1, you can see I am using these classes to connect to the AdventureWorks database and executing a SELECT statement against it. In the first case I am keeping the resultset in a sql data reader (each record is fetched one at a time and hence the associated connection would be busy serving the user of the sql data reader until you call the close method) and in the second case I am keeping it in a data table of a dataset (all records are fetched at one time and stored in a memory structure).

//Create a connection to connect to SQL Server
using ( SqlConnection _sqlConnectionForAdventureWorks = new SqlConnection (
@»Server=ARSHADALI-LAPARSHADALI; Initial Catalog=AdventureWorks;
Integrated Security=SSPI» ))
<
_sqlConnectionForAdventureWorks.Open ();
//Create a command to execute
SqlCommand _sqlCommand = new SqlCommand ();
_sqlCommand.CommandText = «SELECT TOP 5 FirstName, LastName, JobTitle
FROM HumanResources.vEmployee» ;
_sqlCommand.CommandType = CommandType .Text ;
_sqlCommand.Connection = _sqlConnectionForAdventureWorks ;

/* Data Reader Demo */
//Execute the command and store the data result-set into a data reader
SqlDataReader _sqlReader = _sqlCommand.ExecuteReader ();
//Read each record from data reader at a time
while ( _sqlReader.Read ())
<
Console .WriteLine ( string .Format ( «<0>, <1>, <2>» , _sqlReader[«FirstName»] ,
_sqlReader[«LastName»] , _sqlReader[«JobTitle»] ));
>
_sqlReader.Close ();

/* Data Adaptor and Dataset Demo */
//Execute the command and store the data result-set into a data table of a dataset
DataSet _dataSet = new DataSet ();
SqlDataAdapter _sqlDataAdaptor = new SqlDataAdapter ();
_sqlDataAdaptor.SelectCommand = _sqlCommand ;
_sqlDataAdaptor.Fill ( _dataSet );
//Iterate through the records and columns to get its specific values
//A dataset may contain more than one datatable, as becuase I am using a
//single query to fill one datatable, I am using 0 indexer below
foreach ( DataRow _dataRow in _dataSet.Tables[0].Rows )
<
foreach ( DataColumn _dataColumn in _dataSet.Tables[0].Columns )
<
Console .Write ( _dataRow[_dataColumn.ColumnName] + «, » );
>
Console .WriteLine ( «» );
>
>

If you look carefully at the above code, even though it works fine you will notice two problems when it comes to portability and reusability. First, the connection string is hard coded in the code itself and hence you cannot port this code to another environment unless you make required changes in the code. Second, some of the classes here are specific to a SQL Server implementation (SqlConnection, SqlCommand, SqlReader, SqlDataAdapter etc) it means if at some point in time you are required to change the data storage source for example, SQL Server to Oracle or vice versa, you would be required to re-write the data access layer once again for the new data storage source.

ADO .NET 2.0 has come up with solutions for these problems. To solve the first problem it allows you to save configuration/connection details in a configuration file (app.config or web.config) and by using ConnectionStringSettings and ConfigurationManager classes of ADO .NET 2.0, you can connect to the appropriate server just by making the required change in the configuration file as shown below; obviously no code change is required.

name = » AdventureWorksConnectionString »
connectionString = » Server=ARSHADALI-LAPARSHADALI; Initial Catalog=AdventureWorks; Integrated Security=SSPI »
providerName = » System.Data.SqlClient » />

  • name — the friendly name for your connection
  • connectionString — connection string which will be used to connect to the database
  • providerName — data provider unique name, for example for SQL Server its System.Data.SqlClient and for Oracle its System.Data.OracleClient etc.

The ConnectionStringSettings and ConfigurationManager classes are available in System.Configuration namespace (System.Configuratio.dll) and hence you can make the required reference as shown below:

To solve the second problem, ADO .NET 2.0 introduced several new classes (DbProviderFactories, DbProviderFactory and several database provider base classes) which are based on best practices of using design patterns with Abstract Factory Pattern (provides an interface which allows you to create families of related or dependent objects without specifying their concrete classes), and Factory Method Pattern (defines an interface for creating an object, and let subclasses decide which class to instantiate) or more specifically Provider Model Pattern (allows data access to delegate the responsibility of creating objects to another class).

The DbProviderFactories class exposes the GetFactory static method to create a concrete instance of DbProviderFactory on the basis of the passed provider name whereas DbProviderFactory class creates all the necessary concrete classes for a specific provider, for more details click here.

In Code Block 2, you can see I am using ConnectionStringSettings and ConfigurationManager classes to retrieve configuration detail from the configuration file and then passing provider name to the GetFactory method of DbProviderFactories class to instantiate an instance of DbProviderFactory class, which is based on the passed provider name. Next I am using the instance of DbProviderFactory to create a connection, command and data adapter of that type as well. So in nutshell this code will work, even if you decide to change the data source from one provider to another, just by making the required changes in the configuration file i.e. no code change are required.

ConnectionStringSettings _configSettings =
ConfigurationManager .ConnectionStrings[«AdventureWorksConnectionString»] ;

DbProviderFactory _dbProvider =
DbProviderFactories .GetFactory ( _configSettings.ProviderName );

//Create a connection to connect as per provided provider name
using ( DbConnection _dbConn = _dbProvider.CreateConnection ())
<
_dbConn.ConnectionString = _configSettings.ConnectionString ;
_dbConn.Open ();
//Create a command to execute
DbCommand _dbCommand = _dbProvider.CreateCommand ();
_dbCommand.Connection = _dbConn ;
_dbCommand.CommandText =
«SELECT TOP 5 FirstName, LastName, JobTitle FROM HumanResources.vEmployee» ;
_dbCommand.CommandType = CommandType .Text ;

/* Data Reader Demo */
//Execute the command and store the data result-set into a data reader
DbDataReader dbReader = _dbCommand.ExecuteReader ();
//Read each record from data reader at a time
while ( dbReader.Read ())
<
Console .WriteLine ( string .Format ( «<0>, <1>, <2>» , dbReader[«FirstName»] ,
dbReader[«LastName»] , dbReader[«JobTitle»] ));
>
dbReader.Close ();

/* Data Adaptor and Dataset Demo */
//Execute the command and store the data result-set into a data table of a dataset
DataSet _dataSet = new DataSet ();
DbDataAdapter _dbDataAdaptor = _dbProvider.CreateDataAdapter ();
_dbDataAdaptor.SelectCommand = _dbCommand ;
_dbDataAdaptor.Fill ( _dataSet );
//Iterate through the records and columns to get its specific values
//A dataset may contain more than one datatable, as becuase I am using a
//single query to fill one datatable, I am using 0 indexer below
foreach ( DataRow _dataRow in _dataSet.Tables[0].Rows )
<
foreach ( DataColumn _dataColumn in _dataSet.Tables[0].Columns )
<
Console .Write ( _dataRow[_dataColumn.ColumnName] + «, » );
>
Console .WriteLine ( «» );
>
if ( _dbConn.State == ConnectionState .Open )
_dbConn.Close ();
>

The complete code listing of the data access using data provider specific classes (Code Block 1) is provided in the below text area.

The complete code listing of the data access using data provider independent classes (Code Block 2) is provided in the below text area.

Apache Software Foundation

Быстрые ссылки

Вложенные страницы
  • Data Access Layer
  1. Страницы
  2. Home
  3. Developers
  4. Development 101
  5. Working with CloudStack Code

Data Access Layer

  • Создал(а) Alex Huang , редактировал(а) William Lieuranceиюн 23, 2013

Things to Know

The first thing to know about CloudStack’s Data Access Layer is that it is represented by the VOs in the cloud-engine-schema project. The underlying database is just one particular implementation of that schema. What this means is that a VO may be part of a table or a VO may be a join of multiple tables. The software above the VO layer should not care. To it, the schema is the VO.

The second thing to know about CloudStack’s Data Access Layer is that it utilizes Java Persistence annotations. Thus, any type of ORM, such as Hibernate should work with some tweaks. In fact, we recommend using ORM like Hibernate for any type of API access to the schema. However, there are some caveats so please read through this whole section before rushing to convert everything.

The third thing to know about CloudStack’s Data Access Layer is that the current set of VOs in cloud-engine-schema should not be used for API access. This set of VOs is a normalized view of the relations in CloudStack. It is meant to be used by CloudStack’s job processing engine. When access through the API, the CloudStack schema should be much more descriptive. For example, the VM VO contains the account database id but the VM Resource/Response should contain the account name and account UUID but not the account database id. Thus, VO != Resource/Response. There has been an effort in cloud-server to create database views that define the CloudStack Resource/Response but it is not complete and does not cover all of CloudStack’s Resources/Responses yet.

Where should you look for examples?

Given the above, there’s a natural direction on where to look for examples of how to add database access to CloudStack.

  • If you are writing core cloud-engine (orchestration) code or subsystem plugin code (such as Nicira) and you need access to the database, look at the VOs and DAOs in cloud-engine-schema.
  • If you are writing code for API access and your code is not involved in the orchestration and provisioning of hardware resources, then you should look at the VOs and DAOs in cloud-server, particularly the ones that ends with JoinVO. If you can convert these JoinVOs to use a generic ORM implementation so that JPQL can be used to form complicated searches, that’s even better. I look forward to someone contributing in this area.

CloudStack chose to implement its database access layer using DAO because CloudStack at it’s core is a clustered job processing engine and direct access to the schema is desired. CloudStack also wanted to enforce the following database usage patterns:

  • When a first class entity is deleted in CloudStack, it should not be deleted from the database until an admin runs an expunge process on the database. This allows mistakes to be recovered easily. It also can be used to comply with data retention policies. However, when a entity is deleted, the business logic should no longer see this entity in its operations. This pattern is enforced when a field in the VO is annotated with @Column(name=GenericDao.REMOVED_COLUMN). When this happens, the DAO layer automatically changes delete operations to instead update the removed column with a time stamp but all search operations will not return rows with that column set.
  • When a first class entity is created in CloudStack, it should record when it was created for auditing purposes. This is a fail-safe to more robust auditing mechanisms implemented in the business logic. With this information, an admin, as a last resort, can look at CloudStack logs around the creation time to figure out what might have happened. This pattern is enforced when a field in the VO is annotated with @Column(name=GenericDao.CREATE_COLUMN). When this happens, the DAO layer automatically inserts a timestamp into the column. We don’t need to rely on business logic to remember to fill in this information.
  • Perform object mapping but not relation mapping. The problem with the relation mapping part of most ORM implementation is that it is very easy for a developer to bring the entire database into memory by specifying a few @OneToMany annotation and eager fetches. CloudStack wants to work directly on the database but yet provide the ease of use and mistake free benefits of object mapping. Therefore, DAO does not support annotations such as @OneToMany and @FetchType.
  • Separate SQL generation from database connection. DAO does not manage database connections nor the databases that’s being connected to. That’s directed by the business logic. This eases support for database replication and partitioning strategies.
  • No support for nested transactions.
  • Auto release of database connection, PreparedStatements and Results.
  • Auto rollback of transactions if not committed.
  • Auto release of db locks.
  • Protection against SQL injection attacks.

CloudStack DAO layer is implemented by four different components

  • GenericDao and GenericDaoBase which automatically provides a set of methods to use.
  • @DB annotation and TransactionContextBuilder to do auto release of Connection, PreparedStatement, and Results.
  • Transaction to manage database connection and database transactions.
  • SearchBuilder to create searches based on the VO.

Writing a new VO and DAO

By creating files similar to the above, you will be able to use the methods inherited from GenericDao to find a row by database id, perform searches, delete rows, etc. You don’t really have to write anything else if that’s sufficient to access your new table. Please note the comments in the classes, summarized below:

  • If your VO is used by other modules, you should declare an interface for it and use the interface to communicate with other modules.
  • The interface should not carry any setters as it should be only consumed and not modified by other modules.
  • The getter and setter methods must follow Java convention by putting «get»/»set» before the field name. The DAO code uses this to find the field that’s been modified when you update your VO object.
  • There is no need to declare an interface for your DAO implementation if you’re not planning for it to be used by other modules. There’s a specific use case for this that I will talk about below.
  • There is no need to have setter methods for the removed field and created field as they are filled in by the DAO code automatically.
  • For the removed and created field, it must use the constants declared in GenericDao. If you put in @Column(name=»removed»), then the DAO code considers that a field your code will update.
  • The protected default constructors are needed for reflection to instantiate the class.

Annotations supported by the DAO implementations

Ссылка на основную публикацию
Adblock
detector