Problem using VerifyTheMappings in Fluent NHibernate - fluent-nhibernate

I'm using Fluent NHibernate to map classes to a database and I'm using PersistenceSpecification.VerifyTheMappings() to verify the mappings in my unit tests.
If ClassA has a property of type ClassB and I want to verify the mapping, I first create an instance of ClassB then I try to use it with PersistenceSpecification like this:
ClassB classB = new ClassB();
new PersistenceSpecification<ClassA>(session)
.CheckProperty(x => x.ClassB, classB)
.VerifyTheMappings();
When I run the test in NUnit, the test fails with the following error:
System.ApplicationException : For property 'ClassB' expected 'MyNamespace.ClassB' of type 'MyNamespace.ClassB' but got 'ClassBProxyf24bc4...' of type 'MyNamespace.ClassB'
I also tried using "CheckReference" instead of "CheckProperty", but I got the same results. Creating the ClassB instance inline within CheckProperty() also didn't make a difference - not that I expected it to...
I've come across code examples on the web that imply that this should work. What am I missing here?

If ClassB is a mapped entity you should use CheckReference rather than CheckProperty.
However, the problem is that you have to help Fluent NHibernate decide if the objects are equal. You can either pass in an IEqualityComparer into the PersistenceSpecification or have your entities override the Equals method.
In the comparer / equals override you would probably want to do something like comparing the types and the primary key values.
There is a section at the Fluent NHibernate wiki about using PersistenceSpecification to test references, which includes a sample implementation of IEqualityComparer.

Related

Accessing properties of a Kotlin entity

I'm new to Kotlin, so apologies if I'm not articulating concepts correctly. I have an instance of an Entity
[TestEntity(applicationId=1, timestamp=2018-01-24T18:40:30, issueState=MA, product=test, status=sold, paymentMode=VISA, premium=null)]
I am writing a service that is going to take these keys and use them to create the headers of a report. The keys may change depending on the type of report the user is trying to generate, which will have an impact on the Entity that will be instantiated.
I want to be able to iterate over this Entity so that I can create an array to use for the headers. Any thoughts on how I do this?
I think the cleanest solution is storing values in a map and delegating properties to it.
Don't think you can otherwise iterate over class fields without some verbose getter chain or ugly reflection shenanigans.
For example here you can access map fields as if they were class fields, but can also easily iterate over map.
data class TestEntity(val map : Map<String, Any>){
val appId : Int by map
val timeStamp : Long by map
(... more fields)
}

How to use custom id serializer with Jackson?

I'm using Jackson 2.1.4 and want to serialize collections of objects that extend an Event class, and where the JSON has to include the class name for polymorphism purposes. I have put a #JsonTypeInfo annotation on Event, but unfortunately I can't use CLASS as strategy, because my object instantiation pattern is "new FooEvent(){{bar=someValue;}}", which will create anonymous inner classes. I want to put in "FooEvent" as the type in JSON, rather than the anonymous inner class.
It seems like what I need is to do this:
#JsonTypeInfo(use= JsonTypeInfo.Id.CUSTOM, include= JsonTypeInfo.As.PROPERTY, property="type")
But how do I register my own custom id serializer that will output the name of the class?
Figured out how to solve this: basically add a #JsonTypeIdResolver annotation on the same class as has #JsonTypeInfo, then implement a resolver which it can refer to. Here's what mine looks like. It essentially just removes anonymous inner class if present.

CF9 ORM Populating an entity with an object

I am using Model-Glue/Coldspring for a new application and I thought I would throw CF9 ORM into the mix.
The only issue I am having right now is with populating an entity with an object. More or less the code below verifies that only one username can exist. There is some other logic that is not displayed.
My first thought was to using something like this:
var entity = entityload('UserAccount' ,{UserName=arguments.UserAccount.getUserName()},"true")
entity = arguments.UserAccount;
How ever this does not work the way that I expected. Is it even possible to populate an entity with an object or do I need to use the setters?
Not sure if this is what you're looking for. If you have...
component persistent="true" entityName="Foo"
{
property a;
property b;
}
You can pass a struct in the 2nd param to init the entity (added in CF9.0.1 I believe)
EntityNew("Foo", {a="1",b="2"});
To populate Foo with another object, you can use the Memento pattern, and implement a GetMemento() function to your object that returns a struct of all its properties.
EntityNew("Foo", bar.getMemento());
However, CF does NOT call your custom setters! If you want to set them using setters, you may add calls to the setters in your init() constructor, or use your MVC framework of choice to populate the bean. In Model-Glue, it is makeEventBean().
Update: Or... Here's hack...
EntityNew("Foo", DeserializeJSON(SerializeJSON(valueObject)));
Use this at your own risk. JSON might do weird things to your numbers and the 'yes','no','true','false' strings. :)
Is it even possible to populate an entity with an object or do I need to use the setters?
If you mean "Is it possible to create load an ORM Entity from an instance of that persistent CFC that already exists and has properties set?", then yes you can using EntityLoadByExample( object,[unique] )
entity = EntityLoadByExample( arguments.userAccount,true );
This assumes the userAccount CFC has been defined as persistent, and its username value has been set before being passed in (which seems to be the case in your situation).
Bear in mind that if any other properties have been set in the object you are passing, including empty strings, they will be used as filters to load the entity, so if they do not exactly match a record in your database, nothing will be loaded.

nHibernate, Automapping and Chained Abstract Classes

I'm having some trouble using nHibernate, automapping and a class structure using multiple chains of abstract classes
It's something akin to this
public abstract class AbstractClassA {}
public abstract class AbstractClassB : AbstractClassA {}
public class ClassA : AbstractClassB {}
When I attempt to build these mappings, I receive the following error
"FluentNHibernate.Cfg.FluentConfigurationException was unhandled
Message: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail.
Database was not configured through Database method."
However, if I remove the abstract keyword from AbstractClassB, everything works fine. The problem only occurs when I have more than one abstract class in the class hierarchy.
I've manually configured the automapping to include both AbstractClassA and AbstractClassB using the following binding class
public class BindItemBases : IManualBinding
{
public void Bind(FluentNHibernate.Automapping.AutoPersistenceModel model)
{
model.IncludeBase<AbstractClassA>();
model.IncludeBase<AbstractClassB>();
}
}
I've had to do a bit of hackery to get around this, but there must be a better way to get this working. Surely nHibernate supports something like this, I just haven't figured out how to configure it right.
Cheers,
James
Why do you include abstract classes in your AutoMappings, are they presented in the database too? Could you provide the inner exception Fluent throws?
model.IncludeBase<AbstractClassA>();
model.IncludeBase<AbstractClassB>();
With this in place you are trying to map AbstractClassB to the database, which is supposedly not what you want.

Is there a way to define reusable properties to n-hibernate mappings?

I have a scenario that i want to add some standard properties to my entities. Meaning that i will have e.g. 1 int and 2 string properties applied to all relevant entities. I have over 100 mapping files and most but not all will be hosts to these new properties. In the classes its easy to define this; in the mappings however i've found no reference other than creating a utility or xslt and applying that (How to define reusable <generator> elements in hibernate mapping).
However i want to be able to add/modify/remove properties from this "standard" mapping.
thx for any replies
Edit1: an example of the mapping i want to add
<property name="TimeOfEdit" column="TimeOfEdit" type="DateTime" not-null="true"/>
<many-to-one name="EditedBy" column="FK_EditedBy" cascade="save-update" not-null="true" />
Edit2:
I removed the accepted solution because with NH 2.1.1 XML Entities are not working (NH-1236) and NH will throw a "DTD is prohibited in this XML document"
It depends on how these properties are implemented in your classes.
If they are all defined in a base class or interface, you could map them once in the base class or interface, and derive using union-subclass. There are some limitations. Read this chapter in the NHibernate documentation about it.
If you decide to put them together into a class, you could map them as a user type. This will be similar to a component, but you could specify some things like type names, lengths and others in the user type. You still need to specify each column name.
There is another option: you could use XML entities. This is a rather primitive feature from XML which is supported by NHibernate. Read this chapter in the NH reference documentation where it is mentioned.
Creating a special code generator for your specific case is your only option.
Option 1:
-Define these 3 properties in a base class
-have your entities inherit from this base
-set up 'table per class hierarchy'
Option 2:
-Define these 3 properties as a component.
-You can have the mapping for these 3 properties in one file that is reused.
You might take a look at fluentNHibernate, It will simplify the mapping work for you. With With auto mapping you may only need an abstract base class to define these properties.
It seems that the only to do this, is to use Dynamic Mapping (http://ayende.com/Blog/archive/2008/05/01/Dynamic-Mapping-with-NHibernate.aspx)
as such since i've already defined an interface that my entities will use for the new properties (lets say IAuditable) its just a matter of running the appropriate code at the NH-session initialization
Configuration cfg = new Configuration() Mappings mappings = cfg.CreateMappings();
foreach (var persistentClass in mappings.Classes)
{
if (persistentClass.MappedClass is IAuditable)
{
...
}
}
and then
cfg.BuildSessionFactory();
to have it wired up and ready to be used
for about 85 classes the performance impact is negligible