NHibernate DetachedCriteria Orders removed - nhibernate

my work is using NHibernate 2.0.1.4000 for .NET. We are trying to upgrade to later version (3+) but cannot due to changes in DetachedCriteria. In 2.0, you can use DetachedCriteria.AddOrder(order), and then DetachedCriteria.Orders to get the list of the Order objects. In later versions, DetachedCriteria.Orders is gone. Is there another way to get the list of Order? We have code that checks if count is 0. For example:
if (criteria.Orders.Count == 0)
{
criteria.AddOrder(Order.Asc("User.FirstName"));
criteria.AddOrder(Order.Asc("User.LastName"));
criteria.AddOrder(Order.Asc("User.Login"));
}
Thanks

No, you can't, unless you're willing to use reflection. The inner CriteriaImpl field is private, as you can see here: https://github.com/nhibernate/nhibernate-core/blob/ad4c2ef101cbf8ba798220973f4f78dd795e0896/src/NHibernate/Criterion/DetachedCriteria.cs.
You will need to keep track of that collection yourself.

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");

Spring.Net HibernateTemplate.Execute Clarification

I am taking over a project that was written by third party consultants who have already left.
I come from EF backgournd. One of the DAO class has the following which I find very hard to get my head around on details of what is exactly happening step by step. If anyone could kindly help me to understand this code section will be much appreciated.
return HibernateTemplate.Execute(
delegate(ISession hbSession) // <<--What is this code actually trying to do?
{
string queryText = "from {0} x where x.Code = :Code";
queryText = string.Format(queryText, typeof(Product));
IQuery query = hbSession.CreateQuery(queryText);
query.SetParameter("Code", productCode);
query.SetCacheable(true);
query.SetCacheRegion(CoreCacheConstants.ProductQueryCacheRegion); // <-- What is this code trying to do.
var fund = query.UniqueResult(); // <-- Is this similar to DISTINCT keyword in LINQ?
if (fund == null)
throw new ArgumentException(String.Format("No product found with productcode: {0}", productCode: ));
NHibernateUtil.Initialize(((Product)Product).Details); // <--What is this code trying to do. And where is the execute method for above queries.
return fund;
}
) as Product
Basically I am confused with delegate part and why delegate is being used instead of simple query to database. And what is the benefit of above approach.
Also I cant see any nHibernate ORM mapping xml. Does Spring.NET requires mapping files in order to pass data from/to data source?In order words how does ISession knows which database to connect to and which table to use etc
This is what in the spring documents is referred to as Classic Hibernate Usage. It is not the currently recommended approach to work with NHibernate, which is described in the chapter on object relational mappers.
The "convenient" usage of delegates here is basically done to provide the HibernateTemplate the means to manage a session and hand this managed session over to other custom methods (in this particular case an anonymous method). (I think it's an implementation of the visitor pattern, btw).
Using this approach, the classic HibernateTemplate can provide functionality to methods it doesn't "know of", such as opening and closing sessions correctly and participating in transactions.
The query is actually being executed by HibernateTemplate.Execute(myMethod); I imagine it creates and initializes a session for you, does transaction management, executes your method with the managed session and cleans everything up.
I've never used HibernateTemplate, but I'm sure it would require mapping files and a SessionFactory, so if this code is hit during execution and doesn't throw any exceptions, the configuration for those has to be there somewhere!
With respect to the questions (besides the delegate part) within your posted code: the use of NHibernateTemplate hasn't really got anything to do with it: you can just as well run this code in any piece of code where you've got hold of a valid ISession instance:
the session executes a HQL query; this query is added to the query cache. I've never used SetCacheRegion myself, but apparently it gives you "fine-grained control over query cache expiration policies".
query.UniqueResult
NHibernateUtil.Initialize

WCF RIA Services SP1, Entity Framework 4, updating only changed columns

I use LinqToEntitiesDomainService class to update database with Silverlight 4 client.
There's AttachAsModified extended method for entity framework ObjectContext which allows you supply original entity property values:
Order original = this.ChangeSet.GetOriginal(currentOrder);
this.ObjectContext.Orders.AttachAsModified(currentOrder, original);
By default, WCF RIA Services doesn't send original values to the server, so one needs to
apply [RoundtripOriginal()] attribute to his/her entity.
However, even if I supply original values, SQL generated by Entity framework updates all columns, not only changed ones. Since AttachAsModified() method isn't native ObjectContext class method (it's extended method defined in ObjectContextExtensions class), I tried to use
ApplyOriginalValues method which is defined in ObjectSet class. No change.
It seems entity framework 4.1, which was released recently may have solution (not sure). How about entity framework 4? Is it possible EF to generate sql to update only changed columns?
AttachAsModified will mark the entity as modified. Subsequently (quote from MSDN):
When you change the EntityState of an
entity object entry to Modified, all
of the properties of the object are
marked as modified, regardless of the
current or original values.
Caveat; I haven't done this but, it should work.
Instead of using AttachAsModified, mark the entity as UnChanged using the ChangeState method.
Then use the SetModifiedProperty method on the properties that have changed to have them included in an update.
EDIT: If you want a way to find which properties have changed, there are a couple of articles out there explaining how to do so using the ObjectStateManager such as this one
I did ask similar question on MSDN forums, and it is confirmed that WCF RIA Services will change all columns. Alternative is,
You can fetch a copy from database, compare and mark SetModifiedProperty manually by using reflection.
// change state of entity as Unmodified/Unchanged...
original.EntityState = Unchanged;
// this is copy form database...
// Use different context
MyOrderContext context = new MyOrderContext();
Order dbOriginal = context.Orders.First( x=>x.OrderID == original.OrderID);
foreach(PropertyInfo p in copy.GetTypes().GetProperties()){
Object originalValue = p.GetValue(dbOriginal);
Object newValue = p.GetValue(original);
if(originalValue!=null && newValue!=null
&& originalValue.Equals(newValue)){
continue;
}
// resetting this will
// make entity's only current
// property as changed
p.SetValue(original,originalValue);
p.SetValue(original,newValue);
}
You may have to change code as per situation, check if property is readonly or not and this is just a sample but it will help you to build upon it.
I managed to do this by first attaching the object and then calling ApplyOriginalValues on the EntitySet. You'll need an object with the original values to do this. This method can also be used to prevent a column from being updated, e.g. for row level security.
NOTE: This unfortunately does not work without retrieving the original entity from the database first. Otherwise only properties that are set to its default value are excluded from the update...

C# 2.0 - Is there any way to do a `GroupBy` with a yielded iterator block?

I'm working with a C# 2.0 app so linq/lambda answers will be no help here.
Basically I'm faced with a situation where i need to yield return an object but only if one if it's properties is unique (Group By). For example,..say i have a collection of users and i want a grouped collection based on name (i might have 20 Daves but I'd only want to see one in my collection).
Now i can think of a bunch of situations where this might be useful but I don't think it's possible in C# 2.0 without my explicitly keeping track of what I'm yielding with another internal list. To do it without I'd need to have access to the previously yielded set to check if they exist.
Am I over-thinking this or does it make sense? Maybe having access to the yield through the IEnumerable<T> interface would make sense so you'd be able to do something like this-
IEnumerable<User> UsersByNameGroup(User userToGroupBy)
{
foreach(User u in Users)
{
if(!yield.Find(delegate(User u){return u.Name == userToGroupBy.Name;})) yield return u;
}
}
No, you'll have to keep track of the generated elements internally. But note that a hash-based lookup datastructure (Dictionary etc.) is sufficient for the purpose of detecting duplicates.
(As a side note: In .NET 3.5, there are builtin GroupBy-Methods)