This list for the IDEAL O/R Framework is somewhat based on a similar list in ObjectRelationalToolComparison (very similar to this list just for Java instead of DotNET.) but has a lot of .NET specific "extra-features". I am 100% sure there is no ORM .NET product that matches all this requirements, but let's see who comes closer:
Frameworks included in the comparison
Additional options to consider:
Additional feature comparison proposals (at least for a VS dev environment):
note: (i've been using Diamond Binding for last couple of projects - not sure if these are must-haves for an OR mapper, but they struck me as nice to have)
- Visual Studio Integration (plugin / source control support (if any files get modified) / intellisense)
- Database continuous integration (can resync schema changes without overwriting code)
- Level of code generation (less is probably better for equivalent functionality)
- Generics! I want IList<Foo>s not FooCollections?
List of Features Compared
- 1. Release Version Number (To indicate which version has been referred to, Maturity)
- 2. "Free" as in "free beer" - no license fee
- 3. "Free" as in "free speech" - source available
- 4. Has mapping GUI (For DataBase to Objects, and Objects to Database)
- 5. .NET ErrorProviderSupport? and DataBinding Support (without me coding ANYTHING) for WindowsForms.NET
- 6. Does not requires manual SQL building, but can easily accept SQL based queries.
- 7. RDBMS support/independence, and the user can easily add support for other databases or persistent mechanisms (XML, Prevalence, etc).
- 8. Integration with an MVC framework (like User Interface App Block) o Metaframework (SpringFramework in Java, for example) for both ASP.NET and WindowsForms (Why we need ObjectRelationalIntegrationWithModelViewController?)
- 9. Supports relationships between objects (User can choose the names and types of the foreign keys)
- 10. Mapping supports grouping (GROUP BY clause)
- 11. Mapping supports aggregate functions (count(), avg(), etc.)
- 12. Includes full support of lazy resolution of all queries
- 13. Maintains single identities for objects returned from queries (aka "uniquing") (i.e., AddressFinder?.findById(1) == AddressFinder?.findById(1));
- 14. Resolves Circular Identities (aka "uniquing") (i.e., "account == account.getCustomer().getAccount()")
- 15. Generates Mapping as well as the Objects themselves, so you don't duplicate information in the .NET Objects and the related mapping information.
- 16. Supports Composite Primary Keys (I don't like this, but sometimes is useful for legacy applications)
- 17. Aggregate Mappings - Single field maps to multiple fields in database. http://martinfowler.com/eaaCatalog/embeddedValue.html
- 18. Supports both many to many and one to many associations
- 19. Supports collections of Strings, Integers, Dates, etc
- 20. Supports inheritance / polymorphic queries
- 21. Supports one to one associations
- 22. Can fetch associated objects using SQL outer joins
- 23. Support for optimistic locking / versioning
- 24. Support for Unit of work / object level transactions
- 26. Providing an ODMG compliant API and/or OCL and/or OPath
- 27. Does NOT require "extra" database tables holding locks, metadata, etc.
- 28. Supports multiservers (clustering) and simultaneous access by other applications without loss of transaction integrity
- 29. This is a question: Requires code generation?
- 30. This is a question: Requires RuntimeReflection??
- 31. Query Caching - Built-in support (developer writes no code). The following two identical queries will hit the database only once. The second time cached results will be returned. Address address = AddressFinder?.selectByPrimaryKey(new Long(1)); assertTrue(address == AddressFinder?.selectByPrimaryKey(new Long(1)));
- 32. Supports sequences and identity/autoincrement columns for primary key generation (Not using the incorrect SELECT MAX method!) (The user can choose the name and type of the primary key field)
- 33. Supports ternary associations
- 34. Supports mapping of one class to multiple tables ( Sometimes legacy databases leave you no choice.)
- 35. Supports mapping of multiple classes to one table
- 36. Supports persistence of properties through private fields (Not very important for me, but I am curious)
- 37. Supports persistence of properties through accessors (get/set methods or properties, and they can be private)
- 38. Supports disconnected operations: Populate objects from database, disconnect, create/remove/modify objects (on client, another Process) and apply changes to database (much) later
- 39. Support for ASP.NET... (It means it plays well with the request/response cycle, allows saving objects in the session, unsaved objects have temporary in memory primary keys that allow transactions spanning multiple requests/responses without writing the transaction into the database, etc) (Visually?, Out of the box).
- 40. Support for Remoting (Visually?, Out of the box). Distributed Objects.
- 41. Support for WebServices (Visually?,Out of the box).
- 42. Support for information exchange with System.Data.DataSet.
- 43. In memory object filtering (Specifically ask for a complex filter on an ArrayList of Objects without hitting the database)
- 44. Batch Update (Update lots of objects without object creation).
- 45. Batch Delete (Delete lots of objects without object creation, for example this is very useful in Cascade Delete for ToMany? relationships).
- 46. Saving Changes with one line of code (ObjectsEngine?.CommitAllChanges?()), does all the inserts, deletes and updates in the right order, without user intervention, and without violating Master/Detail relationships.
- 47. Support for nullable types.
- 48. Support for compile-time feedback and correction of queries (IntelliSense in VS.NET).
- 49. Support for field validation constraints before inserting an object in to the ObjectContext?
- 50. Support for custom business logic validation constraints before saving a UnitOfWork
- 51. Support for ObjectCursors?
- 52. Multi datasource transparent querying.
- 53. Multi datasource transparent querying and saving.
- 54. Non-transactional lazy loading of relationships
The Visual Controversy
You may have noticed that some features ask the question "Visually?", being able to visually databind your objects to the UI is a very important feature for an O/R mapper in the .NET world (because, if a lot of users are going to want the ease of use of the DataSet when using your O/R Mapper in the development of WinUI (WindowsForms.NET) or WebUI (ASP.NET) applications. [Note: I disagree with this; while databinding support is important, it makes little sense to ask for specific ASP.NET/WinForms?/WebService support in an ORM; questions 37 and 39 could be dropped imho]
I think questions for compatibility with ASP.NET/WinForms?/WebService shouldn't be dropped, on the contrary, they should be extended, it would be great to have an O/R Mapper that makes it easier to handle object exchange between ASP.NET sessions (or object reuse between ASP.NET requests) it would also be great if someone makes an O/R mapper that could communicate with its datalayer using WebServices... so that... perhaps, different O/R frontends could communicate with a common O/R backend... Finally, think why a lot of people it is still using the DataSet... IMHO it is mainly because it is very well integrated with VisualStudio, if you want that your O/R mapper become widely used, you need to provide the same level of ease of use, raw power with out ease of use, might make your O/R Mapper very popular with code experts, but it won't make regular visual programmers use it (and there are many more regular visual programmers).
Some people think that DataBinding to the UI is orthogonal to ObjectRelationalMapping. If an object implements the interfaces from the System.ComponentModel? namespace it can be bound to a WinForms? or ASP.NET user interface. That's a separate issue from whether it can be transparently persisted to a relational database. but I disagree... take for example the need to use OpenSessionInView? with NHibernate, in that case the API makes really cumbersome to "transparently load" a previously persisted relationship because NHibernate does not support "Non-transactional lazy loading of relationships" so... ObjectRelationalMapperShouldMakeItEasyForTheUserInterfaceToFetchDataInteractively? ... or not? and... if an
ObjectRelationalMapperDoesNotNeedToMakeItEasyForTheUserInterfaceToFetchDataInteractively? is it really a TransparentObjectRelationalMapper?? What is more important? To be AbleToPersistPlainOldObjects? or to make it EasyToManipulatePersistentObjects? should we go for the AnemicDomainModel? (AbleToPersistPlainOldObjects?) or the RichDomainModel? (EasyToManipulatePersistentObjects?)? Should something like the SeamFramework be built for the DotNet platform to solve this problem?-- LuxSpes
There is also the consideration of the popularity of ComponentbasedScalableLogicalArchitecture. Interoperability with CSLA (or providing a CSLA-like DataPortal?) would also be a merit for a framework that is to be used in a 3+-tier environment. Serialization is a start, but there are other issues required for a remote dataportal to know how to handle the objects.
Questions 45 & 46 added on March 26, 2005.
Details for each criteria
- 1. Release Version Number (To indicate which version has been referred to, Maturity)
- AtomsFramework: 2.2 RC1 (April 2005)
- Diamond Binding: 1.4.0 (Feb 2008)
- GentleNet: 1.2.0
- GURA: 1.1 & 2.1
- NeoFramework: 1.3.2 (June 2005)
- NHibernate: 1.0.2 (January 2006)
- NJDX: 1.6 (February 2007)
- OJB.NET: 0.7 (production stable, but currently lacks documentation)
- LLBLGen Pro: 2.0 (July 2006, 7th major version since release in 2003).
- EntityBroker: 2.67
- Vanatec OpenAccess: 4.3
- Symbiotic: 4.0.3
- 2. "Free" as in "free beer" - no license fee
- 3. "Free" as in "free speech" - source available
- 4. Has mapping GUI (For DataBase to Objects, and Objects to Database)
- 5. .NET ErrorProviderSupport? and DataBinding Support (without me coding ANYTHING) for WindowsForms.NET
- 6. Does not requires manual SQL building, but can easily accept SQL based queries.
- 7. RDBMS support/independence, and the user can easily add support for other databases or persistent mechanisms (XML, Prevalence, etc).
- AtomsFramework: Yes
- Diamond Binding: Yes (only SQL Server seems to be "officially" supported)
- GentleNet: Yes
- GURA: Yes (Supports all OLEDB)
- NeoFramework: Yes
- OJB.NET: No (SQL Server supported, Oracle partly tested, OleDb? partly tested)
- LLBLGen Pro: Yes
- NhibernateLibrary: Yes
- NJDX: Yes for RDBMS independence
- EntityBroker: Partially
- Vanatec OpenAccess: Yes (limited to SQL Server, Oracle and MySQL)
- Symbiotic: Yes (Sql Server/Local DB/Express, Oracle, MySql, Sqlite, PostgreSql)
- 8. Integration with an MVC framework (like User Interface App Block) o Metaframework (SpringFramework in Java, for example) for both ASP.NET and WindowsForms (Why we need ObjectRelationalIntegrationWithModelViewController?)
- AtomsFramework: No
- Diamond Binding: Active Record pattern probably helps here.
- GentleNet: No (and whoever wrote the "why" part should read about SeparationOfConcerns, and get a UIMapper to accompany his ORM).
- GURA: No (This feature is inconsistent with OO design)
- NeoFramework: No
- OJB.NET: No
- LLBLGen Pro: No, though through the code generator engine this can be added with a few templates using our Template Studio IDE.
- NhibernateLibrary: ?
- NJDX: Yes, ASP.NET applications like Pet Shop have been developed using NJDX
- EntityBroker: ?
- Vanatec OpenAccess: Yes
- Symbiotic: No
- 9. Supports relationships between objects (User can choose the names and types of the foreign keys)
- AtomsFramework: Yes - no need to use foreign keys
- Diamond Binding: Yes. Child objects, Lists, Inheritance seem to work out the box.
- GentleNet: Yes
- GURA: Yes
- NeoFramework: Yes
- OJB.NET: Yes
- LLBLGen Pro: Yes, relations are determined automatically as a startpoint.
- NhibernateLibrary: Yes
- NJDX: Yes
- EntityBroker: Yes
- Vanatec OpenAccess: Yes
- Symbiotic: Yes Children, Lists, foreign keys not required.
- 10. Mapping supports grouping (GROUP BY clause)
- AtomsFramework: Yes - via framework not mapping
- Diamond Binding: Yes
- GentleNet: No (Yes though the use of database views)
- GURA: Yes
- NeoFramework: No
- NHibernate: Yes
- NJDX: Yes (Query predicates can have GROUP BY clause)
- OJB.NET: ?
- LLBLGen Pro: Yes - via the framework, not through mapping
- EntityBroker: No
- Vanatec OpenAccess: Yes, in queries
- Symbiotic: Yes, in queries
- 11. Mapping supports aggregate functions (count(), avg(), etc.)
- AtomsFramework: Yes - via framework not mapping
- Diamond Binding: Yes
- GentleNet: No (Yes though the use of database views)
- GURA: Yes (Through GURA data gate)
- NeoFramework: No
- NHibernate: Yes
- NJDX: Yes
- OJB.NET: ?
- LLBLGen Pro: Yes - via the framework, not through mapping. Typed Lists (views designed from entity attributes) do support aggregates through mapping.
- EntityBroker: AFAIK only Count.
- Vanatec OpenAccess: Yes, in queries.
- Symbiotic: No other than count for returned collections.
- 12. Includes full support of lazy resolution of all queries
- 13. Maintains single identities for objects returned from queries (aka "uniquing") (i.e., AddressFinder?.findById(1) == AddressFinder?.findById(1));
- 14. Resolves Circular Identities (aka "uniquing") (i.e., "account == account.getCustomer().getAccount()")
- 15. Generates Mapping as well as the Objects themselves, so you don't duplicate information in the .NET Objects and the related mapping information.
- AtomsFramework: No
- Diamond Binding: Yes (partial classes and metadata on attributes)
- GentleNet: Yes (metadata is embedded using custom attributes, and runtime database schema analysis).
- GURA: No (separate tool coming soon)
- NeoFramework: Yes (via NHibernate.Mapping attributes)
- NJDX: Yes
- OJB.NET: Yes (medatata is specified in an XML configuration file which can be generated using the 'pogen' tool)
- LLBLGen Pro: Yes, metadata is generated into the code. Generated code is 'specializing' code of generic classes (through inheritance + strategy pattern)
- EntityBroker: Yes
- Vanatec OpenAccess: Yes
- Symbiotic: Yes (metadata is embedded using custom attributes)
- 16. Supports Composite Primary Keys (I don't like this, but sometimes is useful for legacy applications)
- AtomsFramework: Yes
- Diamond Binding: Yes (but not recommended)
- GentleNet: Yes
- GURA: Yes (supports full composite objects)
- NeoFramework: Yes
- NHibernate: Yes
- NJDX: Yes
- OJB.NET: Yes (but Composite Foreign Keys are not yet officially supported)
- LLBLGen Pro: Yes
- EntityBroker: No
- Vanatec OpenAccess: Yes
- Symbiotic: No
- 17. Aggregate Mappings - Single field maps to multiple fields in database. http://martinfowler.com/eaaCatalog/embeddedValue.html
- AtomsFramework: Yes - map single fields (eg structures or small objects) using "value.attribute" syntax
- Diamond Binding: No (but can be mapped by exposing properties)
- GentleNet: No (but can be mapped by exposing inner class fields as properties on outer class)
- GURA: Yes (fully customisable translations at data type,object type and data field levels)
- NeoFramework: No
- NHibernate: No
- NJDX: No
- OJB.NET: No
- LLBLGen Pro: No
- EntityBroker: No
- Vanatec OpenAccess: No
- Symbiotic: No
- 18. Supports both many to many and one to many associations
- AtomsFramework: Yes. Many to many requires no extra classes.
- Diamond Binding: Yes. (Works out the box)
- GentleNet: Partial (GentleList? class provides automatic 1:n and n:m list management; query-builder does not directly support joins)
- GURA: Yes (supports n:n:n)
- NeoFramework: No (many to many only supported in object model)
- OJB.NET: Yes
- LLBLGen Pro: Yes
- NhibernateLibrary: Yes
- NJDX: Yes
- EntityBroker: No support for many to many
- Vanatec OpenAccess: Yes
- Symbiotic: No support for many to many
- 19. Supports collections of Strings, Integers, Dates, etc
- 20. Supports inheritance / polymorphic queries
- 21. Supports one to one associations
- 22. Can fetch associated objects using SQL outer joins
- AtomsFramework: No - all generated queries use left joins.
- Diamond Binding: Yes (query optimisation will automatically do this)
- GentleNet: Partial (can fetch associated objects by resolving FK relationships in code)
- GURA: Yes
- NeoFramework: No
- NHibernate: Yes
- NJDX: (Fetches associated objects using a separate query)
- OJB.NET: Yes (support for left, right and full outer joins)
- LLBLGen Pro: Yes, though not through inefficient joins but through prefetch paths which allow fetching of graphs with 1 query per node, using subqueries.
- EntityBroker: Unknown
- Vanatec OpenAccess: Yes
- Symbiotic: Yes
- 23. Support for optimistic locking / versioning
- 24. Support for Unit of work / object level transactions
- 26. Providing an ODMG compliant API and/or OCL and/or OPath
- AtomsFramework: No
- Diamond Binding: HQL and Expressions
- GentleNet: No
- GURA: No (Can map ODBMS systems without this)
- NeoFramework: Partial support for OPath
- NHibernate: HQL
- NJDX: No
- OJB.NET: No
- LLBLGen Pro: No
- EntityBroker: No
- Vanatec OpenAccess: Yes, OQL (in addtion SQL, LINQ)
- Symbiotic: No
- 27. Does NOT require "extra" database tables holding locks, metadata, etc.
- AtomsFramework: Yes
- Diamond Binding: Yes
- GentleNet: Yes (nothing "extra" required)
- GURA: Yes
- NeoFramework: Yes (nothing "extra" required)
- NHibernate: Yes (nothing "extra" required)
- NJDX: Yes (One table required for sequence generator though)
- OJB.NET: Yes
- LLBLGen Pro: Yes (nothing extra required)
- EntityBroker: Yes
- Vanatec OpenAccess: Yes
- Symbiotic: No
- 28. Supports multiservers (clustering) and simultaneous access by other applications without loss of transaction integrity
- AtomsFramework: No - And an O/R persistence layer is not normally a physical server like a database server.
- Diamond Binding: Yes
- GentleNet: N/A (not sure what is meant by this)
- GURA: Yes
- NeoFramework: Yes
- NHibernate: ?
- NJDX: Yes (locks are held at the database level so transactional integrity in not compromised)
- OJB.NET: No
- LLBLGen Pro: Yes
- EntityBroker: Unknown
- Vanatec OpenAccess: Yes
- Symbiotic: Yes
- 29. Is pre-compile-time code generation required?
- AtomsFramework: No
- Diamond Binding: Yes (One-click resync, providing Intellisense support)
- Playing around with this further - you can resync from the command line, we managed to get sync, build and then unit tests working - so we basically have full continuous integration with our database now :)
- GentleNet: No
- GURA: No
- NeoFramework: Yes
- NHibernate: No
- NJDX: No
- OJB.NET: No
- LLBLGen Pro: Yes
- EntityBroker: Yes
- Vanatec OpenAccess: No
- Symbiotic: No
- 30. Is reflection used at run-time?
- AtomsFramework: Yes, and also schema reading of the database
- Diamond Binding: Yes
- GentleNet: Yes (schema analysis/reading is optional but provides useful metadata)
- GURA: Yes
- NeoFramework: Yes (not for mapping and creation of objects, though)
- NHibernate: ?
- NJDX: Yes
- OJB.NET: Yes
- LLBLGen Pro: No
- EntityBroker: Yes
- Vanatec OpenAccess: Yes (only for metadata creation on database open, not for mapping and creation of objects)
- Symbiotic: Yes
- 31. Query Caching - Built-in support (developer writes no code). The following two identical queries will hit the database only once. The second time cached results will be returned. Address address = AddressFinder?.selectByPrimaryKey(new Long(1)); assertTrue(address == AddressFinder?.selectByPrimaryKey(new Long(1)));
- AtomsFramework: Yes
- Diamond Binding: Yes (multiple caching strategy support, including custom strategies)
- GentleNet: Yes
- GURA: Yes
- NeoFramework: Yes
- NHibernate: Yes
- NJDX: Yes (if READONLY caching for the Address class is enabled)
- OJB.NET: Yes
- LLBLGen Pro: No, as this can lead to incorrect usage of data as the second query returns 'stale' data while another thread might have updated the data in the db.
- EntityBroker: Yes
- Vanatec OpenAccess: Yes
- Symbiotic: No
- 32. Supports sequences and identity/autoincrement columns for primary key generation (Not using the incorrect SELECT MAX method!) (The user can choose the name and type of the primary key field)
- 33. Supports ternary associations
- 34. Supports mapping of one class to multiple tables ( Sometimes legacy databases leave you no choice.)
- AtomsFramework: Partial - must be done using inheritance.
- Diamond Binding: Partial - maps the exact database relationship (inheritance/1:1)
- GentleNet: Yes (but only in the sense that the table name is dynamic; a single class is always stored in one table).
- GURA: Yes
- NeoFramework: No
- NHibernate: Yes
- NJDX: Yes
- OJB.NET: No
- LLBLGen Pro: Yes, using inheritance.
- EntityBroker: No
- Vanatec OpenAccess: Yes
- Symbiotic: Yes, using inheritance, or implementing an interface.
- 35. Supports mapping of multiple classes to one table
- 36. Supports persistence of properties through private fields
- AtomsFramework: No - all attributes must be public properties
- Diamond Binding: Yes
- GentleNet: Yes
- GURA: Yes
- NeoFramework: No (Neo uses System.Data.DataRow? to store mapped properties)
- NHibernate: Yes
- NJDX: Yes
- OJB.NET: Yes
- LLBLGen Pro: No
- EntityBroker: No
- Vanatec OpenAccess: Yes
- Symbiotic: No
- 37. Supports persistence of properties through accessors (get/set methods or properties, and they can be private)
- 38. Supports disconnected operations: Populate objects from database, disconnect, create/remove/modify objects (on client, another Process) and apply changes to database (much) later
- AtomsFramework: Potentially - but unproven
- Diamond Binding: Yes (Plain serializable .Net objects)
- GentleNet: Yes
- GURA: Yes
- NeoFramework: Yes (Can consume and provide System.Data.DataSet)
- NHibernate: Yes
- NJDX: Yes
- OJB.NET: Yes
- LLBLGen Pro: Yes even over remoting/webservices
- EntityBroker: Yes
- Vanatec OpenAccess: Yes
- Symbiotic: Yes
- 39. Support for ASP.NET (It means it plays well with the request/response cycle, allows saving objects in the session, unsaved objects have temporary in memory primary keys that allow transactions spanning multiple requests/responses without writing the transaction into the database, etc)(Visually?, Out of the box).
- AtomsFramework: Unknown
- Diamond Binding: Yes (Built in database session-per request support, use of web application cache)
- GentleNet: Yes, although objects are uniquely identified by the primary key fields, which can be initialized from code or on insert. However, there is special support for caching and uniqing to ensure safe operation in ASP.NET environments.
- GURA: Yes
- NeoFramework: Unknown
- OJB.NET: Unknown
- LLBLGen Pro: Yes, fully supports ASP.NET 2.0 with own datasource control and 2-way databinding. Also fully support for ASP.NET 1.x and object serialization in viewstate/session.
- NHibernateLibrary: No, objects do not have a temporal primary key, they only get a primary key when saved so it is hard (impossible?) to reference them from controls like the Web DataGrid?, you have to add manually support for temporal primary key... or save to the database on each request/response cycle.
- NJDX: Yes (Assign primary key using sequence generators)
- EntityBroker: Yes objects do have a temporal primary key, they get it when they are created in memory so it is easy to reference them from controls like the Web DataGrid?, and save only when the business transaction is ready.
- Vanatec OpenAccess: Yes
- Symbiotic: No
- 40. Support for Remoting (Visually?, Out of the box). Distributed Objects.
- AtomsFramework: Untried
- Diamond Binding: Yes (Plain serializable .net objects can be remoted and moved between machines)
- GentleNet: Yes (including serializable exceptions)
- GURA: Yes (don't touch any business object)
- NeoFramework: Yes
- NHibernate: ?
- NJDX: Yes (NJDX is totally non-intrusive; the classes don't need to be modified to be used with NJDX; so objects can easily be remoted without any dependency on the OR-Mapping layer)
- OJB.NET: Partly (the object graph will be automatically serialized/deserialized stopping at a non-loaded reference or collection)
- LLBLGen Pro: Yes, full remoting support, including serialized exceptions.
- EntityBroker: Yes
- Vanatec OpenAccess: Yes, .NET serialization support and a more comfortable way of packaging various objects in a container(change-tracking and minimal change set calculation)
- Symbiotic: Yes
- 41. Support for WebServices (Visually?,Out of the box).
- AtomsFramework: Yes (no special support applicable)
- Diamond Binding: Yes
- GentleNet: Yes (no special support applicable)
- GURA: Yes (No affect on serialisation)
- NeoFramework: Yes
- NHibernate: Yes
- NJDX: Yes (OR-Mapping is orthogonal to Web Services. One may use NJDX to implement the business logic of a web service.)
- OJB.NET: Yes (no special support applicable)
- LLBLGen Pro: Yes full webservice support, including cyclic references, hashtables etc.
- EntityBroker:No
- Vanatec OpenAccess: Yes
- Symbiotic: Yes
- 42. Support for information exchange with System.Data.DataSet.
- AtomsFramework: No
- Diamond Binding: Partly
- GentleNet: No (though Gentle provides a light-weight SqlResult? class for similar purposes)
- GURA: Yes
- NeoFramework: Yes (Neo bases objects and unit of work on DataSet)
- NHibernate: Partly
- NJDX: ?
- OJB.NET: No (FindDataSet? can be used when you require arbitrary, read-only data across multiple tables)
- LLBLGen Pro: Partly
- EntityBroker:No
- Vanatec OpenAccess: Yes
- Symbiotic: No
- 43. In memory object filtering (Specifically ask for a complex filter on an ArrayList of Objects without hitting the database)
- AtomsFramework: No
- Diamond Binding: Yes (query caching, predicate based filtering on collections)
- GentleNet: No
- GURA: No (Yes Version 3.0,3.5
- NeoFramework: Yes
- NHibernate: ?
- NJDX: No
- OJB.NET: Yes (queries are made against persistable objects rather than directly against the database tables)
- LLBLGen Pro: Yes, developers can use the same compile-time checked query objects against in-memory collections as with a query on the database.
- Vanatec OpenAccess: No
- EntityBroker:No
- Symbiotic: No
- 44. Batch Update (Update lots of objects without object creation).
- AtomsFramework: Yes - using manually provided SQL
- Diamond Binding: Yes (however this is generally not necessary, as Diamond Binding's performance is comparable to the .net sqlclient)
- GentleNet: Yes (using custom statement built using query generator or supplied manually)
- GURA: Yes, using a single SQL method call
- NeoFramework: No
- NHibernate: ?
- NJDX: Yes
- OJB.NET: ?
- LLBLGen Pro: Yes, using a single method call
- EntityBroker:No
- Vanatec OpenAccess: No
- Symbiotic: Yes for Sql Server Bulk
- 45. Batch Delete (Delete lots of objects without object creation, for example this is very useful in Cascade Delete for ToMany? relationships).
- AtomsFramework: Yes
- Diamond Binding: Yes
- GentleNet: Yes (using custom statement built using query generator or supplied manually)
- GURA: Yes
- NeoFramework: Yes (but only for cascading deletes)
- NHibernate: ?
- NJDX: Yes
- OJB.NET: ?
- LLBLGen Pro: Yes, using a single method call
- EntityBroker:No
- Vanatec OpenAccess: No
- Symbiotic: No
- 46. Saving Changes with one line of code (ObjectsEngine?.CommitAllChanges?()), does all the inserts, deletes and updates in the right order, without user intervention, and without violating Master/Detail relationships.
- 47. Support for nullable types.
- 48. Support for compile-time feedback and correction of queries (IntelliSense in VS.NET).
- AtomsFramework: No.
- Diamond Binding: Yes
- GentleNet: Intellisense support and VS integrated help file only.
- GURA: Yes (and for run time translation changes)
- NeoFramework: Yes (if query templates are used, but not for OPath style queries)
- NHibernate: Yes (ICriteria)
- NJDX: No
- OJB.NET: Yes (if the 'pogen' tool is used for code generation)
- LLBLGen Pro: Yes, all queries are built using objects so all queries are fully type safe and support intellisense and are compile-time checked.
- EntityBroker:No
- Vanatec OpenAccess: Yes
- Symbiotic: Yes using custom sql builders.
- 49. Support for field validation constraints before inserting an object in to the ObjectContext? (In O/R mappers that user PONOs (Plain Old .Net Objects) some validation can be executed when the PONO becomes persistent, this validations are typically for very simple things, like not null fields, or comparisons between fields of the same object)
- AtomsFramework: Unknown.
- Diamond Binding: Yes
- GentleNet: Yes. Validation rules can be added as attributes to fields.
- GURA: Yes
- NeoFramework: Unknown.
- OJB.NET: Unknown.
- LLBLGen Pro: Yes: validators for field rules and validators for entity rules.
- EntityBroker:No.
- NHibernate: Yes.
- NJDX: Yes (through callback methods)
- Vanatec OpenAccess: Yes, possible
- Symbiotic: Yes possible via Intercept interface.
- 50. Support for custom business logic validation constraints before saving a UnitOfWork (This validations happens before saving a UnitOfWork (or a single objects) and allows complex logic (like fetching other objects from the database) to validate that the data to be saved is "consistent" from a business logic point of view)
- AtomsFramework: Unknown.
- Diamond Binding: Yes.
- GentleNet: Yes. Validation rules can be added as attributes to fields.
- GURA: Yes
- NeoFramework: Unknown.
- OJB.NET: Unknown.
- LLBLGen Pro: Yes.
- EntityBroker:Yes.
- NHibernate: No.
- NJDX: Partially throgh the callback methods)Yes
- Vanatec OpenAccess: Yes
- Symbiotic: Yes possible via Intercept interface.
- 51. Support for ObjectCursors? (A cursor is a logical connection to the persistence mechanism from which you can retrieve objects using a controlled approach, usually several at a time,it very useful to batch process a large number of objects)
- 52. Multi datasource transparent querying (For example, it can be configured to read from many databases at the same time, from the perspective of the ORM user all data seems to come from the same database, but when committing, needs a separate commit for each database)
- AtomsFramework: Unknown.
- Diamond Binding: No
- GentleNet: No.
- GURA: Yes
- NeoFramework: Unknown.
- OJB.NET: Unknown.
- LLBLGen Pro: Yes.
- EntityBroker:No.
- NHibernate: No.
- NJDX: Yes (Multiple datasources can be accessed from the same application but one needs a separate NJDX handle for each datasource)
- Vanatec OpenAccess: Not yet
- Symbiotic: No, possible via overrides.
- 53. Multi datasource transparent querying and saving (For example, it can be configured to read/write transactionally from many databases at the same time for querying, from the perspective of the ORM user all data seems to come from the same database, if the committing of a transaction fails, the operation is transparently rollbacked in all databases)
- 54. Non-transactional lazy loading of relationships
- AtomsFramework: Unknown.
- Diamond Binding: No.
- GentleNet: No.
- GURA: No (isn't appropriate)
- NeoFramework: Unknown.
- OJB.NET: Unknown.
- LLBLGen Pro: Yes.
- EntityBroker:Yes.
- NHibernate: No. (If you want to interactively lazy load the relationships of your PONOs you need to use the "pattern" OpenSessionInView?, I guess this will be another source of controversy... the ObjectRelationalMapperShouldMakeItEasyForTheUserInterfaceToFetchDataInteractively? ?)
- NJDX: Yes
- Vanatec OpenAccess: Yes
- Symbiotic: Yes
- 55. NoStrings and OnceAndOnlyOnce for class/table and field/column names - can (optionally?) function entirely using only existing symbols and reflection-provided strings - the user need never provide a quoted string, which impedes refactoring.
- Diamond Binding: Yes. (Queries are based on code names)
- GURA: Yes
- Symbiotic: Yes
Other Comparisons
Fabrice Marguerie published an article on the criteria to consider when choosing an object-relational mapping tool: http://madgeek.com/Articles/ORMapping/EN/mapping.htm
How-To-Select an Object-Relational Mapping Tool for .NET: http://www.howtoselectguides.com/dotnet/ormapping/ (uncomplete and not up2date)
The sheer size of the wish-list is more evidence that one should avoid O/R mapping tools. OOP is not well-suited for business domain modelling; use it just for machine-centric abstractions. (See OopNotForDomainModeling). OO has its place, but that place is not "everywhere". -t
CategoryDotNet