I read this post last night, and I noticed it was from 2006. I could go either way on the ORM, database thing, but I was just wondering if everything bad Jeff said about OR
Disclosure: I'm the author of RDO.Net.
Yes. I believe existing ORMs are going in the wrong direction - they're trying to map relational data into arbitrary objects which IMHO is simply not possible. In the OO world, the arbitrary object is not serialization/deserialization friendly, because every object has an object reference (the address) that is local to the current process. It's OK when you're dealing with a single object, you will get into trouble when you're facing a complex object graph.
Hopefully this problem can be solved using a different approach, as in RDO.Net: instead of mapping relational data into arbitrary objects, we map the schema of the data as rich metadata (Model that contains columns, primary/foreign keys, validations, etc.), and expose concrete Db, DbTable, DbQuery and DataSet for data access. When performing database CRUD operations, you construct the SQL Abstract Syntax Tree (AST) explicitly using strongly typed OO language, as demonstrated in the following sample C# code, which creates a query and returns a DataSet for hierarchical data:
public async Task> GetSalesOrderInfoAsync(_Int32 salesOrderID, CancellationToken ct = default(CancellationToken))
{
var result = CreateQuery((DbQueryBuilder builder, SalesOrderInfo _) =>
{
builder.From(SalesOrderHeader, out var o)
.LeftJoin(Customer, o.FK_Customer, out var c)
.LeftJoin(Address, o.FK_ShipToAddress, out var shipTo)
.LeftJoin(Address, o.FK_BillToAddress, out var billTo)
.AutoSelect()
.AutoSelect(c, _.Customer)
.AutoSelect(shipTo, _.ShipToAddress)
.AutoSelect(billTo, _.BillToAddress)
.Where(o.SalesOrderID == salesOrderID);
});
await result.CreateChildAsync(_ => _.SalesOrderDetails, (DbQueryBuilder builder, SalesOrderInfoDetail _) =>
{
builder.From(SalesOrderDetail, out var d)
.LeftJoin(Product, d.FK_Product, out var p)
.AutoSelect()
.AutoSelect(p, _.Product)
.OrderBy(d.SalesOrderDetailID);
}, ct);
return await result.ToDataSetAsync(ct);
}