What are the main benefits of the Versioning feature in NHibernate? - nhibernate

In other words, what are the main reasons to use it?
Thanks

Versioning is commonly used to implement a form of concurrency. In tables that can be accessed from different sources at the same time, a column named version is used. Nhibernate notes down the version of an object when it reads it, and when it tries to update it, it first checks that the version hasn't changed. On updating a row, the version column is incremented.

Related

Does DynamoDB have locking by default?

I'm looking over the dynamo documentation and it looks like they have optimistic. I'm wondering if this is used by default or not.
From the documentation, it looks like you need to code up the java application to use the #DynamoDBVersionAttribute annotation and get and set the versions. Without doing this, it looks like you can write to DynamoDB without any sort of locking.
Is that correct?
On a side note, I'm not too familiar with DBs without some sort of locking so what would happen if 2 people wrote to the same item at the same time in DynamoDB without any locking? Say the item we're writing to has 4 fields, would one write completely fail or is it possible that DynamoDB updates 2/4 fields with 1 write, and the other 2 fields with the other write?
You are correct. DynamoDB does NOT have optimistic locking by default. There are various SDKs for DynamoDB and as far as I am aware the only one which provides optimistic locking functionality is the Java SDK.
Here's what the Java SDK optimistic locking actually supports:
Creates an attribute in your table called version
You must load an item from the database before updating it
When you try and save an item the SDK tests that the client item version number matches the one in the table, and if it does, the save is completed and the version number is incremented
This is pretty simple to implement yourself if you are using a different SDK. You would create the version attribute yourself. You would create a wrapper for the putItem method (and any other required save/update operations). You would use the Condition Expression to test that the version number in the database is one less than the version you saving.
To answer the second part of your question, both updates would succeed (assuming you had put no conditions on your update). The first one would make any updates specified, and the second one would come along and overwrite them.
Dynamodb doesn't support optimistic locking by default. As you mentioned, you need to use the annotation in the Java model class in order to use the optimistic locking.
If two threads write to the same item, the Dynamodb item will have the last write data (i.e. last thread which writes the data).

Force version increment without locking table in NHibernate

Can NHibernate somehow force a version number increment without locking the table?
I know I can do this to force a version number increment:
session.Lock(myEntity, LockMode.Force);
But the problem is that this will also aquire a physical lock on the table row, which causes big concurrency issues in my application.
In the Java Hibernate world, this seems to be possible:
session.lock(myEntity, LockMode.OPTIMISTIC_FORCE_INCREMENT);
NHibernate's LockMode.Force appears to be equivalent to Hibernate's LockMode.PESSIMISTIC_FORCE_INCREMENT, with no equivalent to LockMode.OPTIMISTIC_FORCE_INCREMENT.
Comparing the documention of the Java and .NET version, there seem to be several LockModes missing in NHibernate that exist in Hibernate.
Any ideas how to deal with that limitation?
If you use numeric version property you can just assign it to 0 and NHibernate will auto increment it for you.

Schema versioning using Fluent NHibernate

I've tried reading some previous answers but it's not clear whether or not any of them apply to my situation, as far as I can see. Most of the questions seem to refer to web applications. I figure I'm better off stating my requirements and going from there instead of trying to reverse-engineer advice meant for a different situation. I'm essentially asking two questions:
What does (Fluent) NHibernate support that would, in principle, allow me to achieve the requirements? I'd prefer to use the Fluent API if possible;
What am I going to have to write myself to develop a working solution?
Broadly, the requirements are as follows:
What I'd like to do is use FNH to persist and rehydrate models for a desktop application that would have roughly the same usage model as MS Office, for example - that is, work is kept as self-contained files which are loaded into a local instance of the application.
The current version of the application must be able to import files from all previous versions and preserve all information except that which is declared to the user to be unsupported; by 'import' I mean 'transcribe the model information contained in file A into new file B such that file B is fully compatible with the current version, beside that which is declared to be unsupported.'
The current version of the application must be able to export a current model to be compliant with only the most recent issue of the previous major version of the application. It is not required to supply legacy compatibility with any older revisions of the previous major version.
The nature of the product is such that updates to the file format happen fairly frequently - aim to be able to release to the user every six months or so if necessary as a ballpark figure, and are changed in development much more frequently than that.
I have no objection to writing code to handle this, provided that:
The coding does not take an inordinate amount of time for arbitrarily complicated changes to the schema;
I am able to verify whether or not the translation between versions is complete by calling the FNH API through unit tests;
I can verify that any given model will round-trip correctly between versions and only lose data which is declared to the user to be unsupported between product versions;
So, to summarise:
What, if anything, does Fluent NHibernate supply to enable this kind of use-case?
Can the requirements be readily satisfied as they are, or will I have to make them more specific and constrained?
What should I investigate as to coding myself?
I would suggest using a document database, something like RavenDB, MongoDb etc, for what you are trying to do. I think these would be a better fit than trying to force a RDBMS (sql server, oracle etc) and consequently nHibernate to do something that its not all that good at. not to say that it can't, but you will end up jumping through all sort of hoops to accomplish what you are asking.
One thing to note is that Fluent Nhibernate only puts a Fluent API over the Class Mapping of nhibernate.

Entity Framework - Schema Upgrade, Multiple DBMS, and Code First

I'm looking into using Microsoft's Entity Framework in an upcoming project which is a point release of an existing product. Our current product supports two DBMS (Oracle and SQL Server), the schema of each is maintained in separate .sql script files.
The entity framework (4.1) looks appealing because it allows various scenarios to be implemented automatically via code generation, reflection, etc. However, as far as I can tell, some of these benefits appear to be mutually exclusive of others.
For example, to support multiple DMBSes, I am inferring that I would need to use a model or code first design, in which case EF would generate the schema for each according to the model (I have seen little to no posts or documentation on this, so I may be wrong). This means that our existing schema would need to be either abandoned (model-first), or mapped (code-first). Additionally, updating the schema would require manual scripts as EF does not appear to support schema upgrades (without wiping out data).
Are model-first and code-first the only viable means of supporting multiple DBMSes in EF? I realize that technically it would be impossible to guarantee that two arbitrary schemae are the same, so I am thinking this is true.
Are there any potential pitfalls of code-first and mapping to multiple DBMS systems? For example, Oracle does not have auto-increment columns; you have to use sequences. How is this mapped in the DbContext? Do I need to create separate maps for each DBMS?
Does EF support any mechanism to upgrade an existing DBMS schema to one of which is representative of the EF model (schema recreation =/= upgrade), or am I limited to doing this manually?
I did come up with one possible way to use database first and support multiple DBMSes, however it is a maintenance nightmare. The idea was to add another layer of abstraction to the two generated data models and create converter classes for each of the EF generated models. This seems like the best way of doing it so that each DBMS could potentially have its own model, yet my code would handle the mapping. But in doing this, what am I really gaining from EF? Maybe query generation, but is that worth it?
Actually both the model-first and the database-first have same constraints. Both these approaches are using an EDMX file which contains SSDL (a description of store = a database layer) part related directly to a single database provider so if you want to have two different database providers you must have two different SSDL parts and keep them in sync. You can use single CSDL (a description of conceptual layer = your model classes) and a single or two MSLs (a description of mapping between SSDL and CSDL - a single file is possible only if tables and columns will have exactly same names in both SSDLs). As I know EDMX file can consists only from single SSDL, CSDL and MSL parts so I expect that the designer has no support for this scenario and you will have to modify second SSDL manually or use two EDMXs = model each change twice.
The code-first approach can make this much more simple but the question is how good is Oracle provider when using the code-first and the database generation. The provider is responsible for correctly interpreting needed features like sequences in case of auto increment columns.
EF itself currently has no support for upgrading existing DB. When using EDMX the process of the database generation is controlled either by T4 template or Workflow so it can be customized and there is already separate feature called Entity Designer Database Generation Power Pack which allow incremental building of the database with the model-first approach. The problem is that this feature is using VS Database tools. I think these tools works only with SQL server. I never like these automated tools so I still think that database upgrade should be controlled manually with help of some tools to get difference script between the current and the last deployed database versions. You should need diff script only when deploying new the new version to a production environment. In a testing and a development environment you can always recreate the whole database.
There should be no abstraction needed when working with two EDMX models. Models must produce the same conceptual layer. In such case you need only a single set of POCO classes which are mapped by conventions (same class name as the entity, same properties with same types and accesibility) so they will work with both models.
Edit:
Based on #Tridus answer I'm just adding that you can create databases first and use fluentAPI from EF 4.1 to map them. Your databases must have exactly the same schema (table names, column names, etc.), they can't use any specific features (I hope sequences will not be the problem because it is just the way how Oracle handles auto increment columns).
This is actually fairly doable with a database first design, but there's some caveats you won't be able to get around easily due to how the databases handle things differently.
Sequences are one (in that they're just ignored by EF entirely). You can fake that in Oracle by putting a trigger on the table that populates it on Insert, but I also found that if you have to update the model later then EF "forgets" that the column is an identity column and it'll try to stick a 0 in it again. I also found it unreliable in Oracle to try and get the new ID if you use a trigger. We just wound up selecting from the sequence and setting the ID on the object before doing the insert because that's how you usually do it in Oracle. You could also use a stored procedure that handles it.
Numbers aren't handled the same way. SQL Server uses number formats that map to Int32, Int64, etc. Oracle's number format is totally different and a full range Int32 in SQL Server is a Number(10,0) in Oracle... which is actually an Int64 in EF because it's bigger then an Int32. I also found that Oracle's EF provider likes to use Decimal a lot even when it doesn't have to, but that's probably just a beta issue.
Stored Procedures in Oracle require some values to be put in app.config/web.config in order to work in EF. I'm not sure if that's going to just be clutter in SQL Server or if it'll cause problems.
Finally, EF Code First is pretty immature and according to the docs doesn't support changing the database structure in this version. I'm not sure if Oracle's provider supports it either (it might, haven't tried it).
Most of this is stuff you can get around, but you're going to need to do some work to hide the differences from the rest of your code and it'll probably take a wrapper layer to do it.
edit - In regards to your #4 - EF 4.1 can generate partial POCO classes. Instead of writing a wrapper around each of the generated models to hide any differences, you can create another partial class code file that won't be regenerated when you update the model, and then add properties/methods that hide the differences. Your app code would just have to be aware to use those instead, and they'd handle the issue (like the number issue I mentioned, you could completely hide it with another property that can do the necessary casting for Oracle).

Execute custom sql for one property in NHibernate

As I understand it NHibernate has a build in support for timestamps. However, it appears you can only instruct NHibernate to never update the property or always update it.
In the project I am currently working on there are several tables which have both "created_time" and "updated_time", both are to be generated by the database.
I can't figure out how to instruct NHibernate to use "getdate()" for both properties nut only on insert for "created_time" and on insert and update for "updated_time".
Is this possible?
PS: I am working with a legacy database and I am not allowed to change it, so triggers etc. are not possible solutions.
You could work around this by creating an Interceptor that sets those values, but offcourse, then those values are not generated by the DBMS offcourse ...
It might be a workaround, as I also don't know how to make sure that the DB populates those values, but I'm also interested in another solution for this issue. :)
Which version of NHibernate are you using?
In 2.0, the "generated" tag on a property has three valid values:
never (self-explanatory)
insert(will retrieve the generated value only on inserts)
always (always retrieves generated value).