On __sleep() i throw away a models property (ObjectStorage of Product). How can this property be restored on __wakeup(), containig all the related products it had before serialization?
Related
There are several Spring Data projects like Neo4j that use the Spring Data Commons to build up a PersistentEntity/PeristentProperty (basically type info plus property geters and setters) and EntityConverter to roll from a native store to Java. This is what the SDN (Spring Data Neo4j) does plus it bundling BeanWrapper converters to make sure that certain property types are allowed for the Neo4j data structure.
Basically Java beans are stamped with a #NodeEntity annotation and the beans is decomposed on writes into nodes (think a bean with only simple properties) interlinked by relationship objects.
Wondering if I can do the same with Orika? Means identifying classes via an annotation and processing each property when complex recursively. For example:
#NodeEntity
class Software {
String name;
....
Organisation organisation;
....
}
#NodeEntity
class Organisation {
String name;
}
Should be rolled into 2 nodes each containing the property name and a relationship object (denotes Organisation as a member of Software).
Here is an example of an Orika ClassMapBuilder supporting custom annotations, I think you can adapt it to meet your needs.
Gist : AnnotationClassMapBuilder
For Node (or DBObject of MongoDB) you can use a custom property resolver, take a look at:
http://orika-mapper.github.com/orika-docs/advanced-mappings.html (ElementPropertyResolver)
Edit
Orika build mappers by class-map which are actually, just a collection of property-pair, property can be any thing which has name, type and setter or/and getter.
You can automatically create for each attribute in your beans an equivalent in Neo4J side, and let Orika build the mapper.
For example you can create a Person(name)->PrintStream mapper,
in which you create for each person's property (name) an equivalent that print data (System.out)
Example
final Builder name = new Property.Builder()
.name("name")
.type(String.class.getName())
.setter("append(\"My name : \").append(%s).append('\\n')");
factory.classMap(Person.class, PrintStream.class).fieldMap("name", name, false).add().register();
factory.getMapperFacade().map(person, System.out); // This print to default output stream, My name : xxxx
My domain objects have a "CreateDate" and "ModidfyDate" members (DateTime).
When a user update a domain object (Asp.Net MVC) my view model does not hold these values. (It's to be set in my repository "Create" and "Update" methods)
So when I Update an object, I do not have the "CreateDate" available and therefore the Update method will fail.
I seems to have 2 options, and I don't like either:
1) Have my viewmodel tag along the "CreateDate" property (hidden field in form) so I have the original CreateDate available.
2) Or, in my "Update" repository method, first get the original record from the database and set the object I'm about to update's CreateDate member (an unnecessary call to the db)
What is the "normal" way to work with this?
A nice way to handle CreateDate and ModifyDate would be by using NHibernate's event listeners.
Here are some samples on how to create simple auditing using IPreInsertEventListener and IPreUpdateEventListener:
http://ayende.com/blog/3987/nhibernate-ipreupdateeventlistener-ipreinserteventlistener
http://nhforge.org/wikis/howtonh/creating-an-audit-log-using-nhibernate-events.aspx
On a side note, you shouldn't have problems with CreateDate on your Update method. How does your Update method look like?
The usual workflow is to get your view model in POST ActionMethod, load the entity object from the database using NHibernate's ISession, or your custom repository and then map your properties from the view model to the entity, either by hand, or using a tool like AutoMapper. Properties like CreateDate should be ignored in the viewmodel to entity mapping.
Is there any way to see how the relationships of an Entity were affected/changed inside of a ChangeInterceptor()? Here is an example using NorthWind Database, when you delete/remove an Order Entity from an Employee Entity where the relationship is one-to-many, one Employee has many Orders, how can detect an Order was removed from the Employee Entity. I know using the ObjectStateEntry class you can call GetModifiedProperties() to see what Properties changed, but how do we see what Collections/Associations changed?. Does it have something to do with the RelationshipManager?
[ChangeInterceptor("Employees"]
public void OnChangeEmployees(Employee employee, UpdateOperations operations)
{
//I'm using EntityFramework 4.1
//We have to dropdown the ObjectContext to detect IA, Independant Association, changes
ObjectContext ctx = ((IObjectContextAdapter)this.CurrentDataSource).ObjectContext;
ObjectStateEntry entry = ctx.ObjectStateManager.GetObjectStateEntry(employee);
//What do I do here for detecting relationship changes.. I.E and Order was added?
}
Thanks in advance.
Instead of using a ChangeInterceptor... Just implement the SavingChanges event handler on the ObjectContext. This article explains how to see if an Entity's relationship was affected.
I am trying to construct an SQL statement dynamically.
My context is created dynamically, using reflection finding classes deriving from EntityTypeConfiguration and adding them to DbModelBuilder.Configuration.
My EntityTypeConfiguration classes specify HasColumnName to map the Entity property name to db table column name, which I need to construct my SQL statement.
namespace MyDomain {
public class TestEntityConfig : EntityTypeConfiguration<TestEntity>{
Property("Name").HasColumnName("dbName");
}
}
From What I have researched, it seems I can get access to this information through MetadataWorkspace, which I can get to through ObjectContext.
I have managed to retrieve the the entity I am interested in with MetadataWorkspace.GetItem("MyDomain.TestEntity",DataSpace.OSpace), which gives me access to Properties, but none of the properties, of Properties, give me the name of the mapped db column, as specified with HasColumnName.
Also I am not clear what DataSpace.OSpace is and why my model is constructed in this space.
If Anyone can shed some light on this I would be grateful
UPDATE
Further to #Ladislav's comments. I discovered I can get the information as follows
For the class properties
ctx.MetadataWorkspace.GetItem<ClrEntityType>("MyDomain.TestEntity", DataSpace.OSpace)).Members
For the table properties
ctx.MetadataWorkspace.GetItem<EntityType>("CodeFirstDatabaseSchema.TestEntity",SSpace).Members
So given that I only know the type MyDomain.TestEntity and Memeber "Name". How would I go about to get "dbName". Can I always assume that my mapped class will be created in CodeFirstDatabaseSchema, om order to dynamically construct the identity to retrieve it from SSpace and how would I get to the correct Member in SSpace. Can I do something like
var memIndex = ctx.MetadataWorkspace.GetItem<ClrEntityType>("MyDomain.TestEntity", DataSpace.OSpace)).Members["Name"].Index;
var dbName = ctx.MetadataWorkspace.GetItem<EntityType>("CodeFirstDatabaseSchema.TestEntity",SSpace).Members[memIndex];
MetadataWorkspace contanis several containers specified by DataSpace. Interesting for you are:
CSpace - description of conceptual model (this should contain properties)
CSSpace - mapping of conceptual model to storage model (this should contain how classes / properties are mapped to tables / columns)
I'm wondering what the best design would be for persisteing a new child entity with NHibernate without accidentally overwriting the parent in the database.
The problem I have is that the child entity will look something like this:
class Child
{
Parent Parent;
// other fields
}
My problem is that the child has been supplied from the UI layer along with the ID of the parent, and that means that the Parent ref is basically uninitialized: It will have the ID populated but everything else null - because the only way to populate its fields would be an extra round trip to the database to read them.
Now if I call Session.SaveOrUpdate(child) on NHibernate, what's going to happen with the parent. I don't want NHibernate to cascade save the uninitialized parent since that would just destroy the data in the database. How would people approach this problem? Any best practices?
You must use the session.Load(parentid) to get the aggregate root. In contrast to the session.Get() method, this does not actually fetch any data from the database, it just instantiates a Parent proxy object used to add Child objects to the correct Parent in the DB (eg. get the foreign key correctly).
Your code would probably look something like:
// Set the Parent to a nhibernate proxy of the Parent using the ParentId supplied from the UI
childFromUI.Parent = Session.Load<Parent>(childFromUI.Parent.Id);
Session.Save(childFromUI);
This article explains Get/Load and the nhibernate caches really well
You should probably be working with the aggregate root (probably the Parent) when doing Saves (or SaveOrUpdates etc).
Why not just:
Fetch the parent object using the parent id you have in the child from the UI layer
Add the child to the parents 'children' collection
I think you have to overview your mapping configuration for nhibernate. If you have defined on the reference by the child to the parent that hi has to Cascade all, it will update it!
So if you say Cascade.None he will do nothing. All other are bad ideas. Because you allready has the information of this parent. So why read from db agane?!
If your models looks like this
class Parent
{
}
class Child
{
Parent myParent;
}
and you are trying to set the parent and save the child without having a full parent object, just the ID.
You could try this:
session.Lock(child.myParent, LockMode.None);
before saving, this should tell nhibernate that there are no changes to the parent object to persist and it should only look at the object for the Id to persist the association between Parent and Child