 |
DataObjects.Net is .NET library that
dramatically simplifies development of data and business tiers of the database application. It provides:
- Methodology that standardizes and
simplifies development of persistent classes and services operating with them
providing very clear separation of your business and data tiers from other
parts of an application. Essentially DataObjects.Net requires you to build a hierarchy
of your persistent and business objects over two base classes: DataObject
and DataService. It provides more then 20 attributes controlling almost
any persistence or behavior-related aspect. Don't worry about this number – you can know
nearly 5 of them to start using DataObjects.Net.
- Persistence framework handling all object persistence related
tasks transparently. Moreover, this framework allows to almost
forget that the underlying database exists – it handles even database schema updates.
This framework fully supports inheritance, persistent interfaces,
relations and collections,
object queries, full-text indexing and search,
multilingual properties and a lot of other features.
Use of this framework makes most part of your data tier automatically compatible
with Microsoft SQL Server 2005 \ 2000, MDSE 2000, Microsoft
Access, Oracle, Firebird (formerly – Interbase), MaxDB (formerly – SAP DB) (free,
but one of the most featured database servers) without any additional code.
- Transactional services allowing to almost forget that your
business and data objects operate in the concurrent transactional environment. Transactional services intercept
calls of your business tier methods and wraps them into transactions (outermost
or nested) providing that if exception or deadlock occurs, no data will
be changed. These services are capable of re-processing method call on deadlock
exceptions (and similar). This behavior is provided completely transparently
for developers, but nevertheless it's highly configurable.
- Security system supporting per-instance
access control lists (allow-deny lists),
permissions (custom permissions),
security principals (users and
roles) and permission inheritance.
Its primary goal is to make usage of business objects completely safe, even when these
objects are publicly available – via .NET Remoting, for example.
- All is initially remotable &ndash any persistent object
or business service can be marshaled to another application domain via .NET Remoting (as
well as all other DataObjects.Net-related objects, e.g. Query). This means
that you can access your data and business tier from a completely different
network or across the Internet with almost no additional code. DataObjects.Net
supports two marshalling scenarios: access-by-reference for regular DataObjects
and by-value marshalling for so-called offline entities (data transfer objects).
DataObjects.Net allows you to focus on code of business tier and
application data model – it completely solves a set
of problems that could take up to 80% of development time.
Just imagine, what does it means – to find and fix an error
(e.g. thread deadlock or the latest update wins-like problem) that
appears only under high concurrency conditions. Sometimes it's not so easy to even imagine that
such a problem exists!
DataObjects.Net can be used in virtually any application that accesses a relational database.
You simply add a reference to DataObjects.Net.dll to your project to start using it.
Check out Product Benefits section!
DataObjects.Net is shipped with DataObjects.Net
PetShop (DoPetShop) sample. This is a DataObjects.Net-based clone of the
famous Microsoft .NET Pet Shop. Here are the most interesting comparison facts:
-
DoPetShop contains ~ 50 Kb of data and business tier
code while .NET Pet Shop – 140 Kb (including Business
Logic Layer, Model, DAL and two its implementations – SQL Server DAL and Oracle DAL, but without
BLL\OrderInsert.cs – read further about this). This means that use
of DataObjects.Net reduced business and data tier code size by 3 times! Note
that DoPetShop shipped with latest versions of DataObjects.Net includes a lot of additional
features – for example, it utilizes security system, full-text search and serialization features.
- Moreover, it includes administration module. First version
of DoPetShop that was very close to the original .NET Pet Shop by the feature set
was much smaller – its data and business tier code size was less then
20 Kb, so it was nearly 7
times smaller then its original!
- DoPetShop utilizes DataObjects.Net
access control system – this means that DataObjects.Net takes complete
care about the authentication and authorizes access to application's business objects
- DataObjects.Net brings
true full-text search to DoPetShop, while .NET
Pet Shop always uses like to locate necessary products
- DataObjects.Net, and consequently, DoPetShop, fully supports 6 database server platforms (Microsoft SQL Server 2005 \
2000, MSDE 2000, Microsoft Access, Oracle, Firebird, SAP DB \ MaxDB) while .NET
Pet Shop – only SQL Server 2005 \ 2000 \ MSDE and Oracle
-
DoPetShop provides full, but safe access
to its data and business tier via .NET Remoting (while .NET Pet Shop
allows to perform only one simple operation via its web service), so generally
you can perform any activity remotely, e.g. such manipulations with persistent
objects as creation, changing, deletion. Allowed activities certainly depend on
your security permissions. See DoPetShop Remoting Client – this WindowsForms
application really does this (it shows a lot of other features also, see the screenshot).
- There is only one
Query in DoPetShop sensitive
to database server version! I.e. different values are assigned
to Text property of this Query
instance depending on current database server.
There are some other benefits of DoPetShop, e.g. it provides more information on cart and order-related pages, but may be the most exciting one is that it's extendable with much less amount
of efforts. You can find more information about this sample further.
We believe
DataObjects.Net currently is one of the best tools on the market. It's a complete DAL and RAD tool for your business tier. It offers the richest feature
set. We hope you'll enjoy using it!
Major features of DataObjects.Net:
- Transparent persistence: you don't need to write data access code
for insert\update\delete operations – DataObjects.Net persists instances
transparently for you. This means that you should never think about invoking a Save\Load-like methods also – DataObjects.Net handles such tasks completely
transparently making you fell you're working with ordinary object instances.
Transparent persistence has similar benefits as automatic garbage collection –
you shouldn't worry about persisting your changes. Note that this doesn't mean
all changes are persisted immediately – DataObjects.Net optimizes the update
sequence (see delayed updates feature description).
- Automatic database schema building\upgrading (database schema includes
tables, views, columns, indexes, etc.): on each startup of Domain
its database can be upgraded to support new persistent model (persistent model changes e.g.
when you modify, add or delete some persistent classes). Upgrade process doesn't destroy existing data.
- Instance identification: DataObjects.Net uses unique 64-bit
integers in the database scope to identify instances; upcoming versions will support
GUID and 32-bit integers also.
- Querying: use DataObjects.Net query language (see Query description) or perform a direct SQL query (see SqlQuery description) to select the instances you're interested in. An example of DataObjects.Net query: "Select Animal instances where {LegCount}=4 order by {Name}" – this query fetches all four-legged Animal instances, as well as instances of Animal descendants – e.g. Cats and Dogs). More difficult example selecting grandparents instances: "Select Animal
instances where {Children[{Children.count}>0].count}>0". DataObjects.Net query language supports sub-queries, joins,
distinct and full-text search part in criteria.
- Inheritance support: as it was mentioned, DataObjects.Net fully supports inheritance
for persistent classes. But we went much further here: DataObjects.Net supports
so-called persistent interfaces. This unique feature
allows you to query for objects implementing some interface and refer to its
persistent properties inside query criteria.
-
Highly configurable persistence for instance properties:
-
Multilingual properties (unique feature): you can mark any
property with [Translatable] attribute to specify that it should store independent versions of
its value for each Culture registered in you Domain. This and a set of other features dramatically simplifies
development of multilingual database applications.
-
References: don't worry about loading referenced objects, as well as persisting
them properly – just write a code like cat.Parent = grandCat. Note that if
you'll try to delete the grandCat instance after executing this code, cat will be notified (because it
holds a reference to grandCat). Also
after grandCat deletion cat.Parent will be
automatically set to null.
-
Collections: cat.Children.Add(kittyCat). Paired
collections and reference properties (unique feature) are
supported (so kittyCat.Parent can be automatically
set to cat for the code above). Contained collections
and references are supported as well (if cat.Children is marked
by [Contained] attribute, all instances referenced
by Children collection
will be deleted on cat's deletion).
-
Structs: any struct type can be used as type of persistent
property or item of collection. DataObjects.Net persists such properties into multiple
database columns according to the structure of struct type.
-
[Serializable] properties: properties which type
is marked by [Serializable] attribute
are persisted without any additional coding – they're stored as byte
streams (BLOBs). DataObjects.Net handles references to other persistent entities
inside such serialized graphs in a special way making them to point
to appropriate instances on each deserialization (note that DataObjects.Net
is transactional, so you can find different versions of the same persistent
instance in different sessions).
-
SQL-related attributes are available for almost any type
of persistent properties ([SqlType], [Length]
and similar ones)
-
Indexing: you can apply [Indexed] attribute
to a persistent property to tell DataObjects.Net that an index should be created
on it, or use [Index] attribute to describe a compound index
-
Full-text indexing & search (unique
feature): DataObjects.Net supports full-text indexing and search. Microsoft
Search (available for SQL Server 2005\2000 only) and DotLucene
(free, RDBMS-independent) full-text indexing and search drivers are shipped with DataObjects.Net.
Built-in managed wrapper for Microsoft Index Service filters helps to index almost any
document\file type stored in database or externally. In particular, you can index the
following document types: Microsoft Office files (.doc, .dot, .rtf, .xls, .ppt, etc...), HTML files (.htm,
.html), Adobe PDF files and so on.
-
Built-in NTFS-like security system (unique
feature): DataObjects.Net has extremely powerful security system allowing to define the permission for
any action (e.g. method execution or property access), grant or deny it for a set
of security principals (users and roles) on some persistent instances (like on folders
in NTFS) and enforce its presence by demanding it inside methods or property
assessors of persistent types or DataServices. It brings NTFS-like
security into your business tier with almost zero additional coding!
We want to underline two very important features of this subsystem:
-
Performance: security system is extremely fast – all
passed permission demands are cached, effective permission sets for any
cached DataObject instance are cached too, internal security
notification layer allows any cached DataObject instance to notify
all dependent cached instances on changes in its effective permission set
Normally
a subsequent permission demand on the same instance is quite
fast. This allows DataObjects.Net to execute up
to 4000000 permission demands per second on 2,8GHz P4!
It's almost impossible to implement a security system having the similar
features and performance without implementing all other caching features
DataObjects.Net has. Just imagine the nightmare of implementing the similar
part in your DAL!
-
Immediate effect: all security
restrictions take effect immediately on any
security-related changes in Session –
so it's not necessary to reopen Session \ invoke some method
to apply new security restrictions. When you adding a User
to some Role, granting permission for him or for some role
it belongs to, this immediately affects on its security
restrictions in the current Session – so all
is transparent even in this case. Even rollback of nested transaction
(or rollback to savepoint) immediately affects on security restrictions.
-
Rich data import and export capabilities:
-
Serialization: DataObjects.Net completely supports .NET Serialization, so you can
serialize or deserialize a graph with persistent instances using binary or SOAP
formatters. Custom formatters are supported as well.
-
Adapter component exports persistent instances
to DataSet and imports back the changes.
-
Offline layer provides advanced implementation of well-known DTO (Data Transfer
Object) pattern. It allows to export a set of DataObject
instances to serializable, marshal-by-value ObjectSets, pass them
to the client to operate with them locally and propagate the changes made to them back
to the application server.
-
BindingManager component (unique feature)
establishes two-way bindings between ASP.NET\WindowsForms controls and object properties. It brings
Property-PropertyEditor bindings in contrast to common Property-ControlProperty
bindings – we think this approach is also interesting for developers.
- All import\export tools support VersionID\VersionCode validation
(optimistic updates).
-
Versionizing provides an ability to see the database
at any previous state (point in time). This feature works only if it's
turned on for the whole Domain. Currently
Versionizing is supported by SQL Server 2005 \ 2000 driver only.
-
Automatic transactions (unique
feature – it quite differs from standard COM+ automatic transactions, read more about it further):
DataObjects.Net is completely transactional. It supports automatic transactions
(started with a method call or property access and committed or rolled back based
on result; transactional behavior is controlled by attributes) as well as manual
transactions (you can also start/commit/rollback a transaction manually); nested transactions
and savepoints are also supported.
-
Transparent deadlock handling (unique
feature): in a highly concurrent environment deadlocks are regular.
In case of a deadlock one of the deadlocked transactions (deadlock victim)
is aborted by the database server. Normally it should be re-executed later
by theapplication – this situation is called deadlock handling.
DataObjects.Net is capable of handling deadlocks transparently –
if a deadlock occurs during an automatic transaction, it can be transparently
handled by re-processing of the outermost transaction (re-calling of corresponding method).
-
Data services (unique feature) allows to use all
DataObjects.Net transactional capabilities (automatic transactions, transparent
deadlock handling) with non-persistent classes (DataService descendants). This
feature greatly simplifies development of services operating with persistent
instances. It's very convenient to use this conception to develop common
services of an application, such as Logging Service. Data services are very
close to ServicedComponents of .NET, the difference is that
they are much faster (method calls are intercepted by the runtime proxies rather then .NET
transparent proxies, no COM+ services are used) and easier to use.
-
Runtime services (unique feature) are data
services of special type (RuntimeService descendants) that can
be periodically executed in a special Thread and
Session inside Domain. The purpose
of runtime services is to perform various maintenance tasks periodically. For
example, all IFtIndexer implementors are runtime services that periodically update
full-text indexes.
Transparent persistence, built-in security system, automatic transactions, data services, .NET Remoting and DTO pattern support allows you to build not only the
data access tier with DataObjects.Net, but the whole business tier of your application.
Supported technologies\platforms:
-
6 RDBMS platforms: DataObjects.Net makes most part of your business tier
automatically compatible with Microsoft SQL Server 2005\2000, MDSE
2000, Microsoft Access, Oracle, Firebird (formerly – Interbase), MaxDB
(formerly – SAP DB) without any additional code
-
2 full-text search
engines: Microsoft Search (supports SQL Server
2005\2000 only) and DotLucene (free, RDBMS-independent)
-
.NET Framework 2.0: DataObjects.Net supports all essential
features of .NET 2.0 (generics, nullable types)
-
Mono: core part of DataObjects.Net runs
on Mono, you can find some screenshots
here
-
.NET Framework 1.1/2.0 languages: C# and
VisualBasic.NET are supported. DataObjects.Net also
should support almost any programming language available for .NET – JScript.NET,
J#, Managed C++ (actually this is a feature of almost any .NET application)
-
.NET Remoting: any persistent instance or DataService
can be marshaled to another Application Domain via .NET Remoting (as well as all other
DataObjects.Net-related objects, e.g. Query). This means that you can access these
objects from a completely different network or across the Internet with almost
no additional code; moreover, you can use offline layer – it's
an implementation of DTO (data transfer object) pattern for DataObjects.Net.
-
Distributed transactions: you can enlist any Session
instance in the MS DTC\COM+ distributed transaction.
Performance-related features:
-
Caching speeds up queries and access to referenced
instances by reusing already fetched data. There are two-level caching in DataObjects.Net:
-
Global cache is shared between all Sessions
operating in the same Domain (usually there is one
Domain object per application except NLB clustering case). Global cache
has fixed size, and contains instantiation data for a set of most frequently
accessed objects. The information fetched from this cache is always validated –
i.e. DataObjects.Net uses it only when it really actual. Usually validation
requires much less time then fetching, and moreover, DataObjects.Net gathers validation
data on any query (since it's also quite cheap) – e.g. running a query
with LoadOnDemand option (such queries are quite fast, since they
fetch only two numeric columns from the storage) may lead to zero subsequent fetches (queries),
because all necessary data could be taken from global cache, as well as validated.
-
Session cache is a WeakReference-based
storage caching already instantiated objects, as well as information necessary to instantiate
them or validate the instantiation data cached in the global cache. For example,
if you execute two subsequent queries and process two object sets returned by these queries,
none of processed objects with the same ID will be instantiated
twice, moreover, instantiation data necessary to create it won't be even fetched twice
from the underlying IDataReaders (certainly if these operations are
executed in the same transaction).
-
Two-level caching layer is only a part of caching
techniques used in DataObjects.Net. Lot of data \ intermediates are
cached internally – for example, all evaluated effective permission sets and
effective user's role sets are cached by the security system.
- Lazy instantiation: DataObjects.Net instantiates (creates
in-memory object and fetches its state from the database) referenced objects on the first access attempt. E.g.
evaluation of cat.Children[0].Friends[1].Parent can lead
to instantiation of up to 3 new objects
(cat.Children[0], cat.Children[0].Friends[1]
and cat.Children[0].Friends[1].Parent). The actual number
of fetched objects depends on if these instances were accessed before and
the state of caches.
- Lazy loading (or load-on-demand): [LoadOnDemand]
attribute applied on the persistent property notifies DataObjects.Net
that value of this property should be fetched from the database on the first attempt
to access it. This feature is highly required while working with instances
containing large amount of rarely accessed data (e.g. BLOBs). The similar
behavior is available for queries – it's possible to specify that
QueryResult should internally contain only IDs
of selected objects rather then complete instantiation data, although will transparently
transform these IDs into the DataObject instances
for you (by performing additional queries). This feature helps to keep very large result sets
in memory.
-
Preloading: DataObjects.Net provides a set of ways
to preload a group of load-on-demand properties or collections for the specified
set of objects, or specified set of objects itself – by minimal
amount of queries.
-
Delayed updates: almost all types of updates are delayed by default
and flushed to the database as late as it's possible. Late update sequence
is normally performed by much less number of queries. This feature is almost
equivalent to using BeginUpdate()\EndUpdate() blocks
in the early versions of DataObjects.Net, but always whenever it's possible.
-
DataObjects.Net is optimized for Microsoft SQL Server 2005\2000. Our
performance tests & profiling are performed mainly on SQL Server 2005.
Moreover, we provide support for a set of special features of this database
server family (for example, full-text search and *(max) data types).
-
Only low-level ADO.NET classes are used. We don't use DataSet,
DataTable and other high-level ADO.NET classes to increase the performance.
DataObjects.Net is NOT an ordinary object-relation
mapping tool or API. The main differences in comparison with the most commonly
used tools are:
-
DataObjects.Net is more than
a persistence layer – its feature set (transparent persistence,
built-in security system, automatic transactions,
data services and .NET Remoting support) allows
you to build not only the data access tier, but the whole business tier on it.
-
DataObjects.Net uses classes, their properties and special attributes
as the only information source. No additional files or a database with
existing structures is required. For example, if you want some field to be indexed,
you can apply [Indexed] attribute on it and DataObjects.Net will
automatically create a new index on corresponding database column.
-
DataObjects.Net can automatically upgrade existing database schema
to a new version without any data loss.
Note that you can still use the database built by DataObjects.Net in another
application or even in the DataObjects.Net-based application by any traditional
way. So if your problem would be better solved by direct SQL queries you can use them.
The benefits of using existing relational database to store objects
are obvious: the evolution of the relational database is a process that we have
been watching for the past 30 years; the most
successful relational databases are quite reliable and fast, so to build a new
level on the top of them is one of the most risk-free ways to implement
a new object-oriented database system. This way of storing objects data is also known
as Object-Relational Mapping (ORM).
Here you can find detailed description of DataObjects.Net features.
|
|