Contents tagged with NHibernate

  • So I Created Another Utils Library

    Thought it was time I start my own Utils library (why not everyone else seems to have one), I have things like a UnitOfWork implementation, base Repository class, and plan to add more things as I go.

    This is still a work in progress and I would appreciate any feedback out there, in the meantime I will continue my work on it.

    You can find the project on GitHub @ http://github.com/stefansedich/YetAnotherUtilsLib


    Cheers
    Stefan

  • In Memory SQLite + Unit Test + FluentNHibernate

    UPDATE:

    I have forked fluent NH here: http://github.com/stefansedich/fluent-nhibernate, and added a change so we can just use:

    .Database(SQLiteConfiguration.Standard.InMemory().ShowSql())

    By default the InMemory() helper will now add the pooling support, I sent a push request, so hopefully this hits trunk. Not sure if I was being silly but I do not see a need where you would not pool in memory SQLite anyway.

    ----------------------------------------------------------

    Just playing around with FNH for the first time, getting my unit tests running proved to be a pain, did a Google and had no luck finding a solution to my problem.

    A quick play using the fluent config I found a way to get it working, my full session factory setup is below:

    public ISessionFactory GetSessionFactory() { return Fluently.Configure() .Database(SQLiteConfiguration.Standard.InMemory() .ConnectionString("Data Source=:memory:;Version=3;New=True;Pooling=True;Max Pool Size=1;")) .Mappings(m => m.FluentMappings.AddFromAssembly(typeof(CustomerRepository).Assembly)) .ExposeConfiguration(config => new SchemaExport(config).Create(true, true)) .BuildSessionFactory(); }

    The key was to set the Pooling=True;Max PoolSize=1; in my config, looking at fluent NH the .InMemory() shortcut seems to not set these:

    public SQLiteConfiguration InMemory() { Raw("connection.release_mode", "on_close"); return ConnectionString(c => c .Is("Data Source=:memory:;Version=3;New=True;")); }

    Guess it would be great if it did, but for the time being I will just do it manually.


    Cheers
    Stefan

  • Lazy Loaded One-To-One With NHibernate

    UPDATE 20081114

    The one-to-one solution I had posted turned out not to work for updates, :(, in the end I had to use a many-to-one map with a unique foreign key association to get this to work, the updated example is below. Sorry for my EPIC FAIL :)...

  • Set the value of a version column in NHibernate manually

    My first post in a long time :), look forward to more from me.

    I am currently working on a project and for the first time am using NHibernate, I must say compared to LINQ to Sql I am in love, NHibernate ROCKS! An issue I was having was that I have a version column in my database defined as an integer and then in my NHibernate mapping files have defined a <version> element to map to this column. Now one issue is that in my service methods I do something like this:

    public void Update(MyDTO dto) {

    // Select the item.
    var item = this.repository.SelectById(dto.Id);

    // Map values from DTO to model.
    item.Name = dto.Name;
    item.Version = dto.Version;

    // Call update
    this.repository.Update(item);

    }

    Because I am passing in a DTO object from my UI layer I need to first load the entity from the repository by Id. Then I map across my properties including the version, which in this case was populated from a hidden field on the UI into the DTO. Next I call update, now my initial assumption was that this would work as I excepted for optimistic locking. I thought that for example say the current version in the DB was 2, and the item we are updating is version 1, so it would load the item with a version = 2.

    Then we override the version to 1 and upon update I would expect it to use this version 1 for the optimistic check. WRONG it from what I understand uses the version value which is cached from a copy of the item upon loading it. If you look at the documentation there are 3 types approaches to optimistic concurrency.



    10.4.1. Long session with automatic versioning

    A single ISession instance and its persistent instances are used for the whole application transaction.

    The ISession uses optimistic locking with versioning to ensure that many database transactions appear to the application as a single logical application transaction. The ISession is disconnected from any underlying ADO.NET connection when waiting for user interaction. This approach is the most efficient in terms of database access. The application need not concern itself with version checking or with reattaching detached instances.

    // foo is an instance loaded earlier by the Session
    session.Reconnect();
    transaction = session.BeginTransaction();
    foo.Property = "bar";
    session.Flush();
    transaction.Commit();
    session.Disconnect();
    The foo object still knows which ISession it was loaded it. As soon as the ISession has an ADO.NET connection, we commit the changes to the object.

    This pattern is problematic if our ISession is too big to be stored during user think time, e.g. an HttpSession should be kept as small as possible. As the ISession is also the (mandatory) first-level cache and contains all loaded objects, we can propably use this strategy only for a few request/response cycles. This is indeed recommended, as the ISession will soon also have stale data.

    10.4.2. Many sessions with automatic versioning

    Each interaction with the persistent store occurs in a new ISession. However, the same persistent instances are reused for each interaction with the database. The application manipulates the state of detached instances originally loaded in another ISession and then "reassociates" them using ISession.Update() or ISession.SaveOrUpdate().

    // foo is an instance loaded by a previous Session
    foo.Property = "bar";
    session = factory.OpenSession();
    transaction = session.BeginTransaction();
    session.SaveOrUpdate(foo);
    session.Flush();
    transaction.Commit();
    session.Close();
    You may also call Lock() instead of Update() and use LockMode.Read (performing a version check, bypassing all caches) if you are sure that the object has not been modified.

    10.4.3. Application version checking

    Each interaction with the database occurs in a new ISession that reloads all persistent instances from the database before manipulating them. This approach forces the application to carry out its own version checking to ensure application transaction isolation. (Of course, NHibernate will still update version numbers for you.) This approach is the least efficient in terms of database access.

    // foo is an instance loaded by a previous Session
    session = factory.OpenSession();
    transaction = session.BeginTransaction();
    int oldVersion = foo.Version;
    session.Load( foo, foo.Key );
    if ( oldVersion != foo.Version ) throw new StaleObjectStateException();
    foo.Property = "bar";
    session.Flush();
    transaction.Commit();
    session.close();
    Of course, if you are operating in a low-data-concurrency environment and don't require version checking, you may use this approach and just skip the version check.

    -------------------

    Now if you look at the above it is clear that I am using the third scenario hence why I as having the issues, if I kept the session around for the life of the transaction i.e store in cache when you display the page and then use this session again for the save, the version would have been handled automagically same being if you had the full object and call an Update with it on a new Session.

    But in my case I do not have the full object and am only mapping over a sub set of parameters from my DTO, so I need to first load the item by ID from the session and then map across my parameters, finally calling an update, this is where the issue is. To fix this the solution which I found on the Java forums and adopted was to create an interceptor which would handle the OnFlushDirty method. In here I will compare the Version of the entity being flushed to the Version of the item in the database, this will do what I would like and allows me to set the Version manually.

    The main issue is that there is 1 extra DB call to get the version, but in my case this is minimal. The code for the interceptor is below, it doesn't seem to have any issues as yet but will undergo more testing as time goes by. The solution/ideas came from here: http://forum.hibernate.org/viewtopic.php?t=977889, and was changed to work.


    public class NHInterceptor : EmptyInterceptor {
    private ISession _session;

    public override void SetSession(ISession session) {
    this._session = session;

    base.SetSession(session);
    }

    public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types) {
    ISessionImplementor sessimpl = _session.GetSessionImplementation();
    IEntityPersister persister = sessimpl.GetEntityPersister(entity);
    EntityMode mode = _session.GetSessionImplementation().EntityMode;

    if(persister.IsVersioned) {
    object version = persister.GetVersion(entity, mode);
    object currentVersion = persister.GetCurrentVersion(id, sessimpl);

    if (!persister.VersionType.IsEqual(currentVersion, version))
    throw new StaleObjectStateException(persister.EntityName, id);
    }

    return base.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
    }

    }



    Maybe you find this useful.


    Thanks
    Stefan