Unique and non-nullable in custom content type

Topics: Writing modules
Oct 15, 2014 at 8:32 PM
Edited Oct 15, 2014 at 8:35 PM
I am writing a custom content type for a module and I would like one of the fields to be unique and non-nullable.

I've included the .Unique().NotNull() to the column in Migrations.cs and the database creates properly.

However, with the .NotNull() property set I get the following error from N when I try to create a new content item I get the following exception at Line 96 in the Repository.cs file:
An exception of type 'NHibernate.Exceptions.GenericADOException' occurred in NHibernate.dll but was not handled in user code

Additional information: could not execute batch command.[SQL: SQL not available]

If there is a handler for this exception, the program may be safely continued.
If I hit continue (twice), I eventually get the "null id in Orchard.ContentManagement.Records.ContentTypeRecord entry (don't flush the Session after an exception occurs)" error.

When I remove .NotNull() and only leave .Unique(), I can create a new content item just fine, but when I delete it a record still remains in my custom table in the database, preventing me from creating another record like it in the future.

I am making an effort to integrate everything under the content type paradigm, but should I be taking a different approach?
Oct 16, 2014 at 11:58 AM
Edited Oct 16, 2014 at 12:01 PM
OK, I think I found what I'm looking for. None of what I'll explain will be news to the Orchard experts, but I wanted to post for others looking for help on the same issue.

By digging through the Users module, which obviously implements some sort of unique and non-nullable fields (Username and Email) in a content type (Users), I see how to check if a Username/Email already exists or if the fields are empty, but nothing is reflected in the database schema.

In short, all of the enforcement is in the code, but there is an example in the Users module of how to implement it.

Another item I noted is that when a content item is "deleted" from within Orchard, it actually remains in the database, specifically the Orchard_Framework_ContentItemRecord and Orchard_Framework_ContentItemVersionRecord tables along with whatever table the content type has created, but the "Published" field under the ContentItemVersionRecord is changed to false.

If you delete a content item under Orchard admin and then go to create a new record with the same data in a field you intend to be unique (i.e., delete a user from the admin screen and then register a new user with the same Username and/or Email), the Users module's CheckForUnicity will not flag that there is an existing record since the existing record's "Published" field is false.

You will end up with two entries of the same Username (or Email) in the Orchard_Users_UserPartRecord table.

If somehow you can turn the previous record's Published field under the ContentItemVersionRecord back to true (offhand I don't see a way it can be done without updating it directly in the database), then you will have two Published Usernames that are identical, which defeats the unique requirement for that field.

Again, just some lessons learned by digging through the Users module code to implement a unique and non-nullable field in a content type.
Marked as answer by LorenMaxwell on 10/16/2014 at 5:26 AM