NHIbernate Load via QBE with single column PK - nhibernate

When invoking Session.Load where the class in question contains a composite id, Load expectes the provided criteria to be an example of the object in question with all the PK properties filled in. The problem is that I want to create a generic IRepository interface with a single Load method, always providing a QBE. However, it seems that Load can not handle QBE if the PK is only a single property. Any thoughts?

Have a look at the repository interfaces in the S#arp Architecture project. They expose two interfaces that allow for a standard integer id as well as another other type (eg. your composite key object) to be specified for Get and Load operations. This is probably the route I would take in your case.

Related

How to duplicate an entity with all of its properties and collections

The standard Jspresso action cloneEntityCollectionFrontAction allows to duplicate the selected rows in a table.
The duplication is limited to the current model and do not take account of collections if exist (ie : the collections are not automatically duplicated)
how to deeply duplicate an entity with all of its collections ?
Second related question : I tried to write by myself an action in order to realize the duplication of the collections. Below a part of the action I wrote :
Offer newOffer = bc.getEntityFactory().createEntityInstance(Offer.class);
Offer clonedNewOffer = bc.cloneInUnitOfWork(newOffer);
clonedNewOffer.setCustomer(curOf.getCustomer());
clonedNewOffer.setEndApplicationDate(curOf.getEndApplicationDate());
clonedNewOffer.setName(curOf.getName());
clonedNewOffer.setStartApplicationDate(curOf.getStartApplicationDate());
I called the getter and setter for each property which is not satisfying because if I add new property or collection to the model, the method must be manually updated.
Is there a way to write a more smart / flexible method ?
Hi Vincent,
Regarding the answer you made and your latest proposal, I changed my backend with the following one :
Offer newOffer = bc.getEntityFactory().createEntityInstance(Offer.class);
Offer clonedNewOffer = bc.cloneInUnitOfWork(newOffer);
CarbonEntityCloneFactory.carbonCopyComponent(curOf, clonedNewOffer, bc.getEntityFactory());
bc.registerForUpdate(clonedNewOffer);
But the registerForUpdate failed due to Data constraints are not satisfied error.
I checked the Id property of the clonedNewOffer and the Id is already the same than curOf Id property.
I understand the meaning of a "carbon copy" which is a strictly copy of all the properties, so, from a backend,
how could I duplicate an entity in order to create a new one ?
Both CloneComponentCollectionAction and CloneComponentAction perform the actual component and entity cloning using a configurable strategy that implement IEntityCloneFactory. Jspresso provide 3 implementations of this interface :
CarbonEntityCloneFactory that deals with scalar cloneable properties but ignores all relationships. It's almost never used directly by application code.
SmartEntityCloneFactory inherits from CarbonEntityCloneFactory and deals with relationships the following way :
clone the references if they are compositions or assign the same references to the clone.
add the cloned component to the same collections than the original belongs to.
HibernateAwareSmartEntityCloneFactory inherits from SmartEntityCloneFactory and deals with lazy initialized properties. This is the implementation that is used by default if you use an Hibernate backend.
As a rule of thumb, you can expect the SmartEntityCloneFactory to perform what you expect about references but ignore dependent collections in order to avoid too deep recursive cloning; so what you've experienced is per-design. If you feel like there is room for improvement, feel free to open a feature request on the Jspresso GitHub. Thinking about it, we could maybe do better about composition dependent collections.
When you want to deal with deeper cloning than what's provided by the SmartEntityCloneFactory (or HibernateSmartEntityCloneFactory), the way to go is to create your own cloning strategy. Of course, you can inherit the default strategy and complete the cloning by overriding the cloneEntity method by calling the super implementation and deal specifically with the collections you want to clone.
Once your strategy is implemented, just inject it either globally in the application by replacing the default one, i.e. :
bean('smartEntityCloneFactory', class: 'your.CustomEntityCloneFactory',
parent: 'smartEntityCloneFactoryBase')
or specifically on one of the clone actions of your application by injecting your custom strategy on the action, e.g. :
bean('myCustomEntityCloneFactory', class: 'your.CustomEntityCloneFactory',
parent: 'smartEntityCloneFactoryBase')
action('customCloneAction', parent: 'cloneEntityCollectionFrontAction',
custom:[entityCloneFactory_ref: 'myCustomEntityCloneFactory']
)
Regarding your second related question, if you are inside your entity clone factory implementation (or have access to an instance of it) and want to clone an entity or a component using the strategy, just call the cloneComponent or cloneEntity method.
If you just want to copy all the scalar properties of an entity or component on a clone and don't have access to a clone factory, you can use the following static utility method :
CarbonEntityCloneFactory.carbonCopyComponent(IComponent, IComponent, IEntityFactory)
Using the above method will solve your implementation robustness.

MVC : How to use database to drive validation attributes, or ALTERNATIVES?

In summary, I'm trying to create instance-specific data-annotation attributes at runtime, based on database fields. What I have now works fine for creating the initial model, but falls over when the model is posted-back and the server-validation happens.
(I have the same input model being used in a collection within a viewmodel, but different validation must be applied to each instance in the collection....for example the first occurrence of the input may be restricted to a range of 1-100 but the next occurrence of the same model, prompted for on the same input page, would be a range of 1000-2000. Another may be a date, or a string that has to be 6 characters long.......)
I'll explain what I've done and where my issues are:
I've inherited DataAnnotationsModelMetadataProvider and provided my own implementation of GetMetadataForProperty (This doesn't have any bearing on the validation problem....yet)
I've inherited DataAnnotationsModelValidatorProvider and provided a facade implementation of GetValidators. What I want to do here is create new attributes based on my database-records and then pass those attributes through to the base implementation so the Validators are created accordingly.
However...... GetValidators is called at a PROPERTY level....When it is called with a propertyname that I want to apply validators to, I need to find the applicable DB record for this propertyname so I can find out what attributes I need to create....BUT...I can't get the DB record's key from just a propertyname of the value field.....In fact, the DB key is in the parent model.....So how do I get hold of it?!
I've tried using a static variable (YUK) and storing the key during a call for one property, and retrieving it during another call for my value field property....But because the model is serialised one-way and deserialised the opposite way I end up with my key being out-of-sync with my required attributes.
To add a slight complication I'm also using a custom model binder. I've overridden CreateModel as advised elsewhere on here, but I can't find a way of attaching metadata or additionalvalues to a PROPERTY of my output model....Only to the model itself....but how do I get at MODEL metadata/additionalvalues inside the GetValidators call for a PROPERTY ?
So....My question is twofold.....
1) Can anyone help me get my database-key from my custom-Model-binder to my GetValidators method on my ValidationProvider? Or maybe using my custom Metadata provider?
2) Is there a different, simpler, way of creating validators at runtime based on database records?
I think you are making this far more complicated than it needs to be. You just need to make whatever your validation criteria selectors are part of your view model. They don't necessarily have to be displayed (they can be stored in hiddens if they need to be kept for postback purposes).
Then you can use something like FluentValidation to create rules that say
RuleFor(model => model.myprop)
.When(model => model.criteria == whatever)
.GreaterThan(100)
.LessThan(1000);
Where criteria is whatever value you use to select when your property has to be in a certain range.
So that would mean you build your view model to include the criteria that is used for validation rule selection.
I'd asked this on the FluentValidation forums also and the lack of answers here as well as the advice against using Fluent from there led me to find my own solution (I understand this almost certainly means I'm doing something really bad / unusual / unnecessary!)
What I've ended up doing is assigning my controller static variable in my Custom Model Binder's CreateModel method, where I have access to the entire client model, rather than trying to do it through a custom MetaDataProvider. This seems to work just fine and gets me towards v1 of my app.
I'm not really happy with this solution though so will look to refactor this whole area in the coming months so would still appreciate any other comments / ideas people have about how to implement dynamic validation in a generic way.
I know this is an old question, but I am answering this so that many others can be benefited from this.
Please see the below article where they are loading the attributes from an xml
Loading C# MVC .NET Data Annotation Attributes From XML, Form Validation
I think you can follow the same approach and instead of reading from xml you can read from database and add these rules dynamically based on the model data type
You can refer the below approach also
DataAnnotations dynamically attaching attributes

nHibernate: determine property value before save

we are currently evaluating whether nHibernate supports the requirements for our project. We share the database with another application so that we are not completely free as regards changes to the schema.
Some columns are filled with unique and consecutive numbers (e.g. for invoices). The next number is determined by a stored procedure that also implements a locking algorithm so that the numbers are guaranteed to be consecutive.
On the one hand we could define a trigger on the respective tables that sets the value for the column when an empty or special value is provided. This would require changing the existing database definition - though it might be the most reliable way to implement this.
In order to avoid the change of the database definition we are trying to solve this in the nHibernate ORM. We've first tried to implement a user type that calls the stored procedure in NullSafeSet if an empty value is provided. Unfortunately, the connection and transaction of the provided command are not set yet when NullSafeSet is called.
How can we solve this with nHibernate?
Thanks in advance,
Markus
If you decide to go with trigger route, then you'll need to add generated attribute to your property mapping.
Generated properties are properties which have their values generated
by the database. Typically, NHibernate applications needed to Refresh
objects which contain any properties for which the database was
generating values. Marking properties as generated, however, lets the
application delegate this responsibility to NHibernate. Essentially,
whenever NHibernate issues an SQL INSERT or UPDATE for an entity which
has defined generated properties, it immediately issues a select
afterwards to retrieve the generated values.
Aside from that, I'm not quite sure how would you call stored procedure from NHibernate issued INSERT, without adding a trigger or default constraint on column.
Edit
Looks like NHibernate has a notion of class persisters, through the interface IEntityPersister. Maybe you could hack something out from that.
The persister attribute lets you customize the persistence strategy
used for the class. You may, for example, specify your own subclass of
NHibernate.Persister.EntityPersister or you might even provide a
completely new implementation of the interface
NHibernate.Persister.IClassPersister that implements persistence via,
for example, stored procedure calls, serialization to flat files or
LDAP. See NHibernate.DomainModel.CustomPersister for a simple example
(of "persistence" to a Hashtable).
You could start from NHibernate's source.
If you have the ability to add triggers to database, that would probably be the best, straightforward way, without investing too much time to fight with NHibernate's internals.

Is it better to populate an object's properties in the constructor or when the property is referenced?

Background: I have an object with a dozen or so properties. The object is instantiated by passing a GUID to the constructor. This GUID is a primary key used to retrieve the property values from the database. Each property is stored in a separate table in the database. We are using EF4 to connect to the database.
Is it better to get all the properties at once from the database or is it better to fetch the property values from the database when the property is actually used in the code? What is the recommended best practice?
I would probably change the code to pass a Guid to a static factory method, which then did the lookup, and passed the recovered entity to the constructor. That way the constructor itself doesn't have to do as much work.
In most cases I would do all this eagerly though - it's usually odd to have an object which "feels" simple, but which then does potentially expensive and fallible database lookups when you access properties. And yes, you should strive to fetch everything in one database lookup - unless one of the properties is actually a collection in itself, etc. If it's just a case of fetching simple fields from the database, it would be crazy to perform one lookup per property access - which could end up giving inconsistent data, too.
At my job we use java / hibernate to handle the db related queries. You can configure it either way - lazy fetching waits for the application to request a property, or you can populate the object's properties on the initial query.
I'm not sure of a standard; however for our application we've found that populating the properties first turned out to be much faster. Its probably worth running a handful of tests to see how your application behaves - could be very different from ours.

How can I handle property mappings to other domain classes that aren't yet mapped with NHibernate?

I'm working on a project to replace ADO.NET data access logic using NHibernate where we're not able to map the entire domain model at once. This means we'll have domain classes with property mappings to other domain classes that aren't yet mapped with NHibernate.
Consider a Person class with an Address property (Address being a domain object without an NH mapping and Person being the class I'm mapping). How can I include Address in the Person mapping without creating an entire mapping for Address?
Is it possible to call legacy (ADO.NET) data access logic from a custom PropertyAccessor? If so, is it reasonable?
*I asked this within another question here but didn't get a response. I'm hoping to get one in a more concise question.
In your example even if you didn't create a mapping file for Address, it would potentially be as much work as creating the mapping file itself. There are a some other options you may consider during your transition, like have a custom DAL with a method 'GetPerson', for example, that would NH load person and ADO load address. Not pretty or efficient, but encapsulates the work, so the interface doesn't change when you want to map Address. That being said there are some options for creating custom data tranforms using NHibernate.Transform.AliasToBeanResultTransformer. But really in the end you have to find a good way to chunk out pieces of your domain model. Using a DAL is both good practice and can be a decent bridge out of ADO and into the NH madness.