NHibernate DateTimeOffsetType proxy source? - nhibernate

I have an existing application using NHibernate to load some fairly complex objects from a database (SQL Server 2008 R2) that has been running for quite some time.
Today, I'm encountering the following error when trying to use JSON.Net to serialize my object:
Error getting value from 'DefaultValue' on 'NHibernate.Type.DateTimeOffsetType'.
None of the properties in my NHibernate mappings are using the DateTimeOffsetType, so I suspect that NHibernate is proxying my objects' properties to that somehow.
I have several Nullable DateTime values on my object, but nothing new to my current release.
Where should I be looking to figure out what properties NHibernate is trying use that type for?
What else might I be missing? The error comes when I attempt to serialize using this code:
var converter = new IsoDateTimeConverter();
x.Json = JsonConvert.SerializeObject(myObject, converter);
Again, that code has been in place for quite some time, it's just the problem that is new.

Not really the solution you will have been looking for perhaps, but a solution none the less - I encountered something similar.
In my case I had forgotten to return my DTO from a web api call and the default json serialiser kicking in did this.
Now I map my data object over to a DTO object which has data contract attributes and I serialize that.
Since my DTO is simple and doesn't get NHibernate Proxified this error no longer seems to occur.
Otherwise - I have done this for other Nullable Dates - where I want more control over the serialisation. Define a custom converter for it and do as you wish, but for this Nhibernate Type.
I'd prefer not serialising (or trying to) those proxy types at all though.

to get to know which properties have datetimeoffset as type
var propertiesWithDateTimeOffset = nhConfiguration.ClassMappings
.SelectMany(c => c.PropertyClosureIterator)
.Where(p => p.Type is DateTimeOffsetType)
.Select(p => p.PersistentClass.ClassName + "." + p.Name);
Note: the code doesn't handle components yet but it would be easy to add

Related

Using the DoctrineObjectConstructor, how are new entities created?

I am attempting to use JMSSerializerBundle to consume JSON into Doctrine entities. I need to both create new entities where they do not already exist in the database, and update existing entities when they do already exist. I am using the DoctrineObjectConstructor included in the JMSSerializer package to help with this. When I consume JSON which contains a property designated as an identifier, such as:
{
"id": 1,
"some_other_attribute": "stuff"
}
by attempting to deserialize it, JMSSerializer causes warnings and eventually dies with an exception for attempting to utilize reflection to set properties on a null value. The warnings all look like this:
PHP Warning: ReflectionProperty::setValue() expects parameter 1 to be object, null given in /Users/cdonadeo/Repos/Ubertester/vendor/jms/serializer/src/JMS/Serializer/GenericDeserializationVisitor.php on line 176
If I manually insert an entity with ID 1 in my database and make another attempt then I receive no errors and everything appears to be working correctly, but I'm now short half my functionality. I looked at the code for the DoctrineObjectConstructor class, and at the top is a comment:
/**
* Doctrine object constructor for new (or existing) objects during deserialization.
*/
But I don't see how it could possibly create a new a new entity because after the construct() function has done all of its checks, at the end it calls:
$object = $objectManager->find($metadata->name, $identifierList);
And since the identifier does not exist in the database the result is null which is ultimately what gets returned from the function. This explains why inserting a row in the database with the appropriate ID makes things work: find() now returns a proper Entity object, which is what the rest of the library expects.
Am I using the library wrong or is it broken? I forked the Git repo and made an edit, and trying it out everything seems to work more or less the way I expected. That edit does have some drawbacks that make me wonder if I'm not just making this more difficult than it has to be. The biggest issue I see is that it will cause persisted and unpersisted entities to be mixed together with no way to tell which ones are which, but I don't know if that's even a big deal.
For Doctrine entities use configuration:
jms_serializer:
object_constructors:
doctrine:
fallback_strategy: "fallback" # possible values ("null" | "exception" | "fallback")
see configuration reference https://jmsyst.com/bundles/JMSSerializerBundle/master/configuration

Updating Fluent nHibernate causes problems with missing property

I am trying to update the nHibernate version in my application.
I used nuGet and updated NHibernate v2.1.2.4000 to v3.3.2.4000
And fluent NHibernate from v1.1.0.685 to v1.3.0.733
I was expecting a few issues but the error I'm getting is odd and I can't quite figure it out.
In my "many to many" convention there is this line:
var userDefined = instance.Relationship.Columns.UserDefined.FirstOrDefault();
if (userDefined != null)
{
instance.Relationship.Column(userDefined.EntityType.Name + "Id");
}
The problem is that after the update of the DLLs the "UserDefined" property no longer exists. What I can't understand is whether I need to redefine it somewhere, or whether there's a different way of accessing that property.
I was under the impression that the "UserDefined" property was part of fluent nHibernate.
Does anyone know how to get this one working?
Many thanks
FluentNHibernate refactored the way it represents specified values.
Before there was one value and indicators who set them (default, convention, explicit). Now there are values for all three kinds and when reading it uses something like explicit ?? convention ?? default hence the tests for explicit/user defined values are no longer needed.
Remove all lines but instance.Relationship.Column(userDefined.EntityType.Name + "Id");

Copying NHibernate POCO to DTO without triggering lazy load or eager load

I need to create DTOs from NHibernate POCO objects. The problem is that the POCO objects contain dynamic proxies, which should not be copied to the DTO. I eager load all the collections and references I need to transfer in advance, I don't want NHibernate to start loading referenced collections which I did not load in advance.
Several similar questions on SO received answers which either:
Suggest Session.GetSessionImplementation().PersistenceContext.Unproxy();
Suggest turning off Lazy Loading.
In my case the first suggestion is irrelevant, as according to my understanding it causes eager loading to replace the proxies. In reality, it doesn't even work - it doesn't remove the proxies in my objects. (Any explanation why?)
The second suggestion, turning off lazy loading seems to cause all references and collections to eager load, basically loading the entire DB. My expectation was that if lazy loading is off, and I have not requested a collection, it will not be loaded. (Am I correct that NHibernate offers no such option?)
I am using NHibernate 3.3.1 with fluent configuration.
To reiterate my main question, I need to create DTOs clean of proxies, copied from POCOs which contain proxies, and I don't want to load the data behind those proxies.
Any helpful suggestion which includes example code and automates the process with ValueInjecter / AutoMapper will be immensely helpful.
Edit #1:
Following Roger Alsing's suggestion to use projections, I realized that what I'm actually looking for is a ValueInjecter-like convention based mapping. Here is why. Initially, my DTOs will be defined the same as the model's POCOs. This is due to a large code base which depends on the existing POCOs being transferred on the client-side project.
Using projections, I will have to specify which subset of fields have to be copied, and this subset may be different in each context (as, ideally, a DTO would differ). This will mean a lot of new code introduced to the server side, when there should be the second option.
Using ValueInjecter, I will be able to populate the DTOs by convention in one call, without writing specific projections, or having to maintain those into the future. That is, if I am able to have ValueInjecter ignore Proxy objects.
Given that using projections is a good but not ideal solution in my situation, is there a way to configure something like ValueInjecter to copy POCOs without copying proxies or triggering eager/lazy loads on copy?
I solve this by selecting DTO's as projections using Linq or whatever query language the O/R Mapper may have.
e.g.
return from c in customers
select new CustomerDTO
{
Name = c.Name ,
Orders = c.Orders.Select (o => new OrderDTO {...} )
};
This way, you don't need to resort to reflection magic or any other fancy stuff.
And the query fetches exactly what you need in one go, thus, this is usually much more efficient than fetching entities and then transforming them to DTO's in mem.
(it can be less efficient in some cases incase the resulting SQL query contains extra joins for whatever reason..)
I'm using the following ValueResolver with AutoMapper:
/// <summary>
/// ValueResolver that will set NHibernate proxy objects to null, instead of triggering a lazy load of the object
/// </summary>
public class IgnoreNHibernateProxyValueResolver : IValueResolver
{
public ResolutionResult Resolve(ResolutionResult source)
{
var prop = source.Type.GetProperty(source.Context.MemberName).GetValue(source.Value, null);
var proxy = prop as INHibernateProxy;
if (proxy != null && proxy.HibernateLazyInitializer.IsUninitialized)
{
return source.Ignore();
}
return source.New(prop);
}
}
for ValueInjecter solution I recommend using SmartConventionInjection (you need to copy the code from the linked page into your solution)
and after specify a convention that won't touch the proxy properties
here's a start:
public class MapPoco: SmartConventionInjection
{
protected override bool Match(SmartConventionInfo c)
{
return c.SourceProp.Name == c.TargetProp.Name;
}
}
Take a look on Projections in Introduction to QueryOver in NH 3.0
CatSummary summaryDto = null;
IList<CatSummary> catReport =
session.QueryOver<Cat>()
.SelectList(list => list
.SelectGroup(c => c.Name).WithAlias(() => summaryDto.Name)
.SelectAvg(c => c.Age).WithAlias(() => summaryDto.AverageAge))
.TransformUsing(Transformers.AliasToBean<CatSummary>())
.List<CatSummary>();

Automatically update Entity instance from class MVC 3

I've got a class that closely resembles one of my entities (I use the class for JSON de/serialization because the entity fails conversion to JSON, one of the known gotchyas of JSON + MVC).
Once I deserilize a JSON string into my object, is there a way to automatically update the associated Entity model instance. The property names are the same.
e.g.
'myDeserialized is the deserialized JSON object coming over the wire
Dim entityInstance As DLL.Person = db.getPersonById(myDeserialized.id)
myDeserialized.update(entityInstance)
Where this just goes through and takes all the properties in myDeserialized and updates the same named property in entityInstance?
Or is it possible to just iterate over a key-value pair of all the properties in an object/entity?
I'm looking for something like TryUpdateModel(), but that only works with forms, right? I don't want to tie my data to a form, that's all.
Thanks!
I don't know what type and version of EF you use, but there are very powerful functions for iterating on the entities properties. Which mean you can easily make your update function on the entity or its baseclass' partial (entityInstance.Update(myDesrialized)).
If you use EntityObject, then you can get an ObjectStateEntry for your entities and via this class you can very easily achieve this.
Please let us know what version and type of EF you use (POCO?)

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.