Continuing discussion from CodeProject article

Coordinator
Feb 26, 2015 at 5:00 PM
(this thread is a continuation of the discussion fired up in comments section of the article:
http://www.codeproject.com/Articles/879568/VITA-A-Powerful-and-Flexible-ORM-and-Additional-Bu?msg=5009509#xx5009509xx)

About lazy/eager loading.
VITA is doing lazy loading all the time (for now). For CustomerOrder.Lines property it loads Lines list only when you read it first time. If you are reading Line.Product property in a loop:
foreach(var line in custOrder.Lines) {
  Console.WriteLine(" Product: " + line.Product.Name); 
}
you'll get Product query each time. Yes, EF have include which does this for you - you have to do it explicitly. You can do the same in VITA by executing a simple query right before you do the loop:
var allProducts = session.EntitySet<IOrderLine>().Where(ol = ol.Order == custOrder).Select(ol => ol.Product).ToList();
which brings me to idea that this probably can be wrapped into a generic extension method, so the thing looks as simple as .Include(...). I will definitely play with it.
Also note that EF uses join for include:
here's a quote:
There are serious implications that you should understand when you use the Include method. The main implication is that it is doing a join between all the tables that you want to return and the data is retrieved in a flatten manner in order to materialize all the entities from it.
http://blogs.microsoft.co.il/gilf/2010/08/18/select-n1-problem-how-to-decrease-your-orm-performance/
In general, the long term plan is make this happen automatically, without you saying anything, with smth like "Adaptive Data Access" - when VITA watches how you use the query result and after a couple of times you do n+1, it does Product list fetching automatically behind the scene.
Coordinator
Feb 26, 2015 at 5:12 PM
Answering this:
Db model management - I have exactly the opposite problem. Not being able to control a database migration by hand is a show stopper. I read here on another comment that you can generate the migration sql and apply it manually. Well, then we're talking about the same thing aren't we? Just with some small deviations.

Not exactly the same thing. With VITA, you don't have to manage any DDL scripts while you continue developing the next version. It is only before the deployment you generate the DB update script using vdbtool - much easier process.

Batch updates... Now there's a nice feature. That's the stuff that differentiate you from EF, that's the stuff you need to promote.
Well, not for long it will be unique, looks like EF7 will finally have it. Although still missing pieces. VITA batch script includes BEGIN TRANS/COMMIT into the script, while EF does it outside, so it is still 3 roundtrips for EF, instead of 1.

From my time with NHibernate, it had 2 levels cache. One per session, (makes all sense) and another outside the session, but it had to be implemented by an external plugin, especially for distributing reasons. Plugging here a Redis store should be a win.
NH 2nd level cache is in-process cache, and VITA's equivalent is SparseCache. In general, VITA's cache is in-process(app domain) cached data set, with single-record cache (Sparse cache) which can only server entities by ID like NH level2 cache. But also there is FullSetCache - a number of tables kept fully in memory - and these can serve any query, including LINQ queries. As for external cache like Redis - you can hook whatever you want, the only trouble you'll have to call it explicitly.
Coordinator
Feb 26, 2015 at 5:24 PM
Edited Feb 26, 2015 at 9:38 PM
Authorization on the ORM, you miss understood me. I said that usually Authorization is too complex to be a simple rule of if this user can change this row. Authorization is more tight up to the Business than the data itself.
"But there's nothing there in open source space (or even closed/paid market)" -> Maybe for a reason. Future will tell.

Not sure what you mean by 'too complex to be a simple rule...' Can you please do me a favor - please read Authorization Guide for VITA, on this site, and let me know if you see some concept missing - preferably with some made-up business example.
And the main reason there's nothing there I think - is because nobody figured out how to make it as a reusable piece. Until now :) Authorization is absolutely, critically important, and efforts spent on this in business software are ginormous, but often the result is far from satisfactory. This is my attempt to fix this, and provide generic reusable solution.
As for should it be in ORM... that probably deserves a big post or blog entry of its own. Why things like caching or authorization are better be built into DAL/ORM layer. But short explanation goes like this. If you take an ORM like NH or EF, and try to implement strict biz requirements for proper authorization of every data access (typical in enterprise apps) on top, you end up with code cluttered with authorization checks. You can no longer just query entity from db or read its property (ORM makes it one-liner, nice!), but you have to surround it with crap like

'if (AuthorizationService.CanRead(currentUser, entType, entId, propName)) then read else throw'.

So the advantage of using ORM simply diminishes to almost zero. Record access is no longer one liner. But... if the authorization check is hidden in ORM and is done automatically - this is a different story.
Feb 26, 2015 at 11:12 PM
Edited Feb 26, 2015 at 11:22 PM
that EF uses join for include
Yes I do know that. That's really not an issue, if you think in how the data gets to you in one single round trip. It needs to be flatten out (also 1 result set). Include is definitely a must use tool, but as everything else, shouldn't be abused.

Selects o(n)+1 are my top first reasons on performance degrade on the systems I audit and build. The second is poor made queries beacause people don't know the internals of the systems they use. They call a method and expect to get things done.
It is only before the deployment you generate the DB update script using vdbtool - much easier process
Development is not always fast forward. There are backs and forwards. There is why a DDL script much similar to Migrations (but not quite) eases my live and my deployments by having my database properly versioned. I always know the increments I need to do or not. I simply rely on a different tool than yours.
VITA batch script includes BEGIN TRANS/COMMIT into the script, while EF does it outside, so it is still 3 roundtrips for EF, instead of 1
Well that is what I actually like. the transaction is committed only when I do Save Changes or Rollbacked if I dispose my session/context. Having your batch including the transaction commands, meaning that you'll have nested transactions? And only commit them all after the final SaveChanges?
NH 2nd level cache is in-process cache
NH 2nd Level cache can be plug-able to external providers. only the out of the box provided (SysCache) uses asp.net cache as storage.
is because nobody figured out how to make it as a reusable piece. Until now :)
I like your confidence.

Overall I think this is an ORM tailed to your vision. I don't think it will fit all pockets sizes. In order you to conquer any significant "market share" this need to be flawless. Little things like having the default Auto to be NewGuid and not applicable to ints, (which probably represent still 80% of current usage) makes it hard for adoption.
You're rigth about moving from ints to guids, but you must be aware that NewGuids are not unique.

Right know I'm a bit frustrated because I spent already a 1hour trying to build a sample, and it simple doesn't work. I get a NullReferenceException on
at Vita.Data.Model.DbParamInfo..ctor(EntityCommandParameter owner, String name, DbColumnInfo sourceColumn, Int32 argIndex) in c:\Pulsar\Development\Externals\Vita\Sources\1.Framework\Vita.Core\Data\Model\DbModelClasses.cs:line 309
at Vita.Data.Model.DbCommandInfo.AddParameter(EntityCommandParameter owner, String name, DbColumnInfo column, Int32 argIndex) in c:\Pulsar\Development\Externals\Vita\Sources\1.Framework\Vita.Core\Data\Model\DbModelClasses.cs:line 404
at Vita.Data.Driver.DbSqlBuilder.CreateDbCommandInfo(EntityCommand entityCommand, String name, DbTableInfo mainTable, DbExecutionType executionType, String sql) in c:\Pulsar\Development\Externals\Vita\Sources\1.Framework\Vita.Core\Data\Driver\DbSqlBuilder.cs:line 258
at Vita.Data.MsSql.MsSqlDbSqlBuilder.BuildSqlInsertCommand(EntityCommand entityCommand) in c:\Pulsar\Development\Externals\Vita\Sources\2.Drivers\Vita.Data.MsSql\MsSqlDbSqlBuilder.cs:line 100
at Vita.Data.Model.Construction.DbModelBuilder.BuildCommand(DbSqlBuilder dbSqlBuilder, EntityCommand entityCommand) in c:\Pulsar\Development\Externals\Vita\Sources\1.Framework\Vita.Core\Data\Model\Construction\DbModelBuilder.cs:line 94
at Vita.Data.Model.Construction.DbModelBuilder.BuildCrudCommands() in c:\Pulsar\Development\Externals\Vita\Sources\1.Framework\Vita.Core\Data\Model\Construction\DbModelBuilder.cs:line 75
at Vita.Data.Model.Construction.DbModelBuilder.Build() in c:\Pulsar\Development\Externals\Vita\Sources\1.Framework\Vita.Core\Data\Model\Construction\DbModelBuilder.cs:line 42
at Vita.Data.Database..ctor(EntityApp app, DbSettings settings) in c:\Pulsar\Development\Externals\Vita\Sources\1.Framework\Vita.Core\Data\Database\Database.cs:line 44
at Vita.Entities.EntityApp.ConnectTo(DbSettings dbSettings, String tag) in c:\Pulsar\Development\Externals\Vita\Sources\1.Framework\Vita.Core\PublicAPI\App\EntityApp.cs:line 150
at TestVitaWeb.Web.MvcApplication.CreateDomainApp() in c:\Repository\Kappy2012\TestVitaWeb\TestVitaWeb.Web\Global.asax.cs:line 35
at System.Lazy`1.CreateValue()


Any problems running this against a LocalDb database?
Coordinator
Feb 26, 2015 at 11:22 PM
sorry for your troubles; no localdb should be fine - in fact, Dave's samples are all developed for localdb. I think something is wrong with your entity setup. This definitely means VITA bug, not reporting more meaningful error. The easiest thing to do is if you send me your sample, I will figure it out quickly (by stepping into code). I will contact you directly - just reply with zipped sample
Roman
Coordinator
Feb 26, 2015 at 11:52 PM
your problem is that you declared IOrder.Rows as IEnumerable, should be IList:
    IList<IOrderRow> Rows { get; set; }
but Vita failed here. It did detect the error properly, but I'm trying to run db builder till the end, to report all errors in model if there are any. And it failed to stop at proper point and throw exception. I will fix that in the next drop
Feb 27, 2015 at 7:35 AM

Ofc. Stupid me. Does it support ICollection as well?

Coordinator
Feb 27, 2015 at 4:36 PM
No. It is a convention for 'special automatic' properties - if VITA finds IList<Entity> as property type, it injects automatic lazy load code and other behavior. Otherwise (for IEnumerable<T>) it treats it as simply special type that can possibly have direct support in DB. (like byte[])