Getting Started with Db4o for Eiffel
- Contents
- Step 1: Download Db4o Assembly
- Step 2: Download Reflector for .NET Assembly
- Step 3: Download Source Code of Db4o for Eiffel
- Step 4: Download EiffelStudio
- Step 5: Create an EiffelStudio Project
- Step 6: Add Assemblies to Your Project
- Step 7: Rename Classes to Avoid Name Clashes
- Step 8: Configure Db4o Databases for Eiffel Applications
- Step 9: Open and Close a Db4o Database
- Step 10: Store Eiffel Objects
- Step 11: Retrieve Eiffel Objects
- Step 12: What’s Next
This page provides a step-by-step guide, showing you how to use db4o databases within Eiffel for .NET applications.
Step 1: Download Db4o Assembly
Because of a critical bug in the db4o assemblies before version 7.1.26 (see the issue report "SODA queries return wrong query results for .NET interfaces"), it is important that you download a db4o version later than 7.1.26. Go to the db4o download center to download a db4o assembly.
Step 2: Download Reflector for .NET Assembly
In the implementation we take advantage of the Reflector for .NET assembly to examine Eiffel for .NET assemblies. You can download the assembly from the project homepage or from here.
Step 3: Download Source Code of Db4o for Eiffel
The project is implemented in Eiffel, and its source code is to be imported into your project. Here is the source code.
After downloading the zip file, please extract the file and then move the db4o_for_eiffel
directory to the directory in which your project will reside, say db4o_example
.
Step 4: Download EiffelStudio
It is common that Eiffel developers use EiffelStudio for developing Eiffel applications. You can download it from Eiffel Software or from Origo.
The recommended version for Windows XP is EiffelStudio 6.1.6.9962, other versions of 6.1.x seem to have problems with debugging Eiffel for .NET applications.
Step 5: Create an EiffelStudio Project
Until now you should have a project directory called db4o_example
with the db4o_for_eiffel
directory in it.
Start EiffelStudio, and in the pop-up window select “Microsoft .NET application†and then click “Create†(see screenshot).
db4o_example
and the project location as the location of your db4o_example
directory. Click “Next >â€.
Step 6: Add Assemblies to Your Project
In the “Clusters†panel right-click “Assemblies†and in the context-menu select “Add Assembly ...â€. Then in the “Add Assembly†window specify the location of the db4o assembly Db4objects.Db4o.dll
to import it into the project.
Perform the same steps for the Reflector for .NET assembly Reflector.exe
.
We also need the EiffelSoftware.Runtime
assembly which can be selected in the “Add Assembly†window.
Step 7: Rename Classes to Avoid Name Clashes
In Eiffel for .NET every class must have a unique class name, so we have to rename some classes in Db4objects.Db4o.dll
and Reflector.exe
to avoid name clashes.
Click “Project†in the menu bar and select “Project settings ...â€.
PREDICATE
as DB4O_PREDICATE
and rename FIELD_INFO
as DB4O_FIELD_INFO
.
Reflector.exe
assembly, rename ASSEMBLY
as REFLECTOR_ASSEMBLY
and rename ICONFIGURATION
as REFLECTOR_ICONFIGURATION
.
Step 8: Configure Db4o Databases for Eiffel Applications
Before storing and querying for Eiffel objects in db4o databases, we have to install POINTER_TRANSLATOR
, which is done in the class EIFFEL_CONFIGURATION
. Add the init
method in the APPLICATION
class and call it in the root procedure make
.
init is
-- Set global database configuration.
local
eiffel_configuration: EIFFEL_CONFIGURATION
do
create eiffel_configuration.configure
end
make is
-- Run application.
do
init
--store
--retrieve_qbe
--retrieve_soda
--retrieve_nq
end
Step 9: Open and Close a Db4o Database
To open and close a db4o database, add the following features to class APPLICATION
:
feature -- Database control
db: IOBJECT_CONTAINER
database_file: STRING is "eiffel.db4o"
open_database is
-- Open `db' of `database_file'.
do
db := {DB_4O_FACTORY}.open_file(database_file)
end
close_database is
-- Close `db'.
local
closed: BOOLEAN
do
closed := db.close
end
Step 10: Store Eiffel Objects
Suppose we have a class PARALLELOGRAM
with two attributes height1
and height2
:
class
PARALLELOGRAM
create
make
feature {NONE} -- Initialization
make(h1: INTEGER; h2: INTEGER) is
-- Initialize `height1' with `h1',
-- `height2' with `h2'.
require
h1_positive: h1 > 0
h2_positive: h2 > 0
do
height1 := h1
height2 := h2
end
feature -- Access
height1: INTEGER
height2: INTEGER
end
To store some PARALLELOGRAM
objects we can write
store is
local
closed: BOOLEAN
do
open_database
db.store(create {PARALLELOGRAM}.make(10, 30))
db.store(create {PARALLELOGRAM}.make(20, 40))
close_database
rescue
if (db /= Void) then
closed := db.close
end
end
Step 11: Retrieve Eiffel Objects
Db4o supplies three querying mechanisms: Query-By-Example, SODA Query API and Native Queries.
Query-By-Example
The following query uses Query-By-Example to retrieve all the PARALLELOGRAM
objects whose height1
is equal to 10 and height2
is equal to 30:
retrieve_qbe is
local
template: PARALLELOGRAM
resultos: IOBJECT_SET
closed: BOOLEAN
do
open_database
create template.make(10, 30)
resultos := db.query_by_example(template)
printos(resultos)
close_database
rescue
if (db /= Void) then
closed := db.close
end
end
where printos
outputs the PARALLELOGRAM
objects in the query result to the console:
printos(os: IOBJECT_SET) is
local
p: PARALLELOGRAM
do
from
until not os.has_next
loop
p ?= os.next
if (p /= Void) then
io.put_string("Parallelogram (" + p.height1.out + ", " + p.height2.out + ")")
io.put_new_line
end
end
end
SODA Query API
To retrieve all PARALLELOGRAM
objects whose height1
is greater than 10, you can write the following SODA query:
retrieve_soda is
local
query: QUERY
constraint, subconstraint: CONSTRAINT
resultos: IOBJECT_SET
closed: BOOLEAN
do
open_database
create query.make_from_query(db.query)
constraint := query.constrain({PARALLELOGRAM})
subconstraint := query.descend("height1", {PARALLELOGRAM}).constrain(10).greater
resultos := query.execute
printos(resultos)
close_database
rescue
if (db /= Void) then
closed := db.close
end
end
Native Queries
You should first define a class, say PARALLELOGRAM_PREDICATE
, which inherits from DB4O_PREDICATE
and implements the match
method. The match
method defines whether a candidate object is to be included in the query result or not.
class
PARALLELOGRAM_PREDICATE
inherit
DB4O_PREDICATE
feature
match(p: PARALLELOGRAM): BOOLEAN is
do
Result := p.height1 > 10
end
end
Then you can pass a PARALLELOGRAM_PREDICATE
instance to the IOBJECT_CONTAINER.query
method to get the query result:
retrieve_nq is
local
resultos: IOBJECT_SET
closed: BOOLEAN
do
open_database
resultos := db.query(create {PARALLELOGRAM_PREDICATE})
printos(resultos)
close_database
rescue
if (db /= Void) then
closed := db.close
end
end
Note that you have to run the finalized system to have Native Queries run without exceptions.
Step 12: What’s Next
To ensure a correct way of working with db4o databases within Eiffel applications, you may need to read the User's and Developer's Manual. Furthermore, we suggest you to download and try out this advanced example project when you are reading the manual.
For further advanced features of db4o, such as transaction and concurrency control, maintenance, client-server mode, etc. please visit the db4o documentation page.
Looks Great
One question, Ruihua. At step 7, instead of renaming individual classes, why didn't you just set assembly-wide prefixesDB4O_ and REFLECTOR_ ?
Prefixes for assemblies
Thank you for your hint. I did not know about assembly-wide prefixes. I think it's a good alternative to resolve name clashes.