How are to-many attributes specified in a fetched property? - objective-c

I have two entities, Parent and Child. The Parent entity has a to-many relationship to Child named "children." Child has a String attribute named "childName."
I want to make a fetched property on Parent, let's call it "specialChild" that returns a Child with a particular name, let's say "Special". The following predicates return an empty set when I access the fetched property:
children.childName == "Special"
SUBQUERY(children, $eachChild, $eachChild.childName =
"Special").#count > 0
SUBQUERY(children, $eachChild, ANY $eachChild.childName =
"Special").#count > 0
I believe I'm messing up the predicate somehow, because I'm still pretty inexperienced with them. (and I can find zero documentation from Apple on "SUBQUERY") How am I supposed to specify "the child whose childName is Special" in the Parent's fetched property predicate?
Yes, I am calling -refreshObject:mergeChanges: but I still receive an empty result. Yes, the destination entity is Child.

What you want is parent==$FETCH_SOURCE AND childName=="Special". This gets any Child whose childName is "Special" and whose parent is the object looking up its special children.
Attributes in a fetched property predicate must exist on the destination entity. Here the destination is Child, so you can't use children since that only exists on Parent.
The $FETCH_SOURCE part corresponds to where you'd use self if you wrote the predicate in code. Without that you get every special child, not just the ones attached to the originating Parent. It says, the parent attribute of the child must be the specific instance looking up the fetched property value.

Related

How do I add a CSLA Business Rule that depends on a property contained in the parent?

I am adding a "rounding" business rule to round a decimal property value to the number of decimal places specified in a separate integer property. This works nicely if both properties are members of the business object in question. As in the following VB.Net code...
BusinessRules.AddRule(New Round(_decimalProperty, _precisionProperty))
I have a private Round class that inherits from CommonBusinessRule and its constructor is as follows:
Public Sub New(decimalProperty As IPropertyInfo, precisionProperty As IPropertyInfo)
MyBase.New(decimalProperty)
InputProperties = New List(Of IPropertyInfo)()
InputProperites.Add(decimalProperty)
InputProperties.Add(precisionProperty)
End Sub
This triggers the rule Execute whenever either property changes, and the Execute code rounds just exactly like I want.
The Problem: I now have a situation where the precisionProperty is a property of the Parent business object. When the CSLA method for adding Business Rules for the Child Business Object is called, the Parent member of the Child Business Object is null, so I can't get to a reference of the parent's property. Is there any point in time AFTER the Parent field is no longer null, that I am allowed to add a new Business Rule? If so in what method? Is there another approach?
We have looked into passing down a reference to the parent business object (via constructors) to the child, but have decided against this approach for now (the child is actually 6 levels deep, and it appears this would require rework of our code generation schemes).
The parent property in the BusinessBase is generally used by the BusinessListBase to keep a relationship with its children. The parent property really isn't(shouldn't be?) used outside of that.
When I have a parent object with a property that affects child objects, I put the rule in the parent object that will then invoke any rules on the child object. You can pass in any values you like, even to the point of having a copy of the property on the child and just setting that as the parent property changes.

Inserting parent and children with NHibernate at the same time

I am attempting to save(insert) a Parent entity with list Child entities. Both entites use a Guid as primary keys. The keys are none nullable and there is no key relationship set up in the db.
The save doesn't work, an exception is thrown claiming - that I am trying to save a null into Parent foreign key in the Child table.
I was expecting nhibernate to create a key for the Parent and let its Child objects know about it. Is this a limitation of NHibernate or of using Guids as primary keys?
This answer suggests you have to set the parent manully, is this really the only way?
Here are my mappings for reference:
Parent mapping:
HasMany(x => x.Children).KeyColumn("ParentKey").Inverse().Cascade.All();
Child mapping:
References(x => x.Parent).Not.Nullable().Column("ParentKey");
NHibernate is not magic. It is only an ORM, if your children do not have their reference set to the parent, why would it assume that because the parent has a list of children that the childrens' reference, in turn, SHOULD be a reference to the parent?
I believe you answered your own question when you stated that the Child entities don't have their Parent property populated (which means it is null, which means NHibernate would be attempting to save a 'null' value for the Parent id in your Child table).
If you were to use these objects WITHOUT NHibernate it would make sense that the Parent reference needs to be set on the Child entities when they are added.
EDIT: This is for the case where you have specified 'Inverse' on your mapping. If you were to remove this call to 'Inverse,' it should work the way you wanted it to work as Inverse states that the other end (the child entity) is responsible for keeping track of the relationship. This means you need to set the reference of the parent on the child manually.
However, removing the Inverse statement would cause the Child(ren) to be saved, the parent to be saved, then the Child(ren)'s parent id to be UPDATED. Since you have a null constraint on the parent id, this means it still won't work as it would initially insert the Child with a parent id of null.
The two solutions would be to either remove this constraint, or to just add a method to the Parent called AddChild:
public void AddChild(Child childObj)
{
childObj.Parent = this;
Children.Add(childObj);
}
Add another method called RemoveChild:
public void RemoveChild(Child childObj)
{
if (Children.Contains(childObj))
{
Child.Parent = null;
Children.Remove(childObj);
}
}
Then, just use those methods for adding/removing children.

Get the ID of a child entity just after a parent has been saved

There is a parent entity that has a collection of child entities (cascale=all) and each child entity has a collection of grand-child entities (cascale=all).
Given a session, I create a grand-child and add it to the children of a child in the parent and since I also modified some other objects inside the hierarchy, I call Session.SaveOrUpdate on the root (parent).
After this I need the id of the grand-child entity but it is 0.
Now if I additionally call Session.SaveOrUpdate on the grand-child too, then I can get its new id. Is it normal behavior? With the cascades set to all, I would have thought that I could get the id when saving the parent.
Any enlightments?
SaveOrUpdate, when called on an already-persistent interface does nothing.
You can either call session.Persist(parent), which will cascade, or call session.Save(grandChild) as you're already doing (there's nothing wrong with this, although I wonder what you need that Id for)

setfirstresult & setmaxresult in child collection

I have and entity lets call it Entity, and a Child collection Children.
I have a screen where the user has the Entity information, and a list with the Children collection, but that collection can be get very big, so i was thinking about using paging: get the first 20 elements, and lazy load the next only if the user explicitly presses the next button.
So i created in the Entity Repository a function with this signature:
IEnumerable<Child> GetChildren(Entity entity, int actualPage, int numberOfRecordsPerPage)
I need to use the setfirstresult and setmaxresult, not in the Agregate root Entity, but in the child collection. But when i use those two configurations, they allways refer to the entity type of the HQL/Criteria query.
Other alternative would be to create a HQL/Criteria query for the Child type, set the max and first result, then filter the ones who are in the Entity Children collection (by using subquery).
But i wasn't able to do this filter. If it was a bidirectional association (Child refering the parent Entity) it would be easier.
Any suggestions?
Any
One approach would be to create a query that returns results from both tables by doing a group by. This approach would allow you to apply paging on data that will come from the children collection and have a common factor (the entity's ID in each row) while you keep your starting point (the Entity object). What I mean is something like that:
public IList<object> GetData(int entityID, int actualPage, int numberOfRecordsPerPage)
{
ICriteria criteria = _repository.Session.CreateCriteria<FlowWhatIfProfile>("entity")
.CreateCriteria("Children", "children", NHibernate.SqlCommand.JoinType.InnerJoin)
.Add(Restrictions.Eq("children.EntityID", entityID));
ProjectionList pl = Projections.ProjectionList();
pl.Add(Projections.GroupProperty("children.Id"));
pl.Add(Projections.GroupProperty("children.Property1"));
pl.Add(Projections.GroupProperty("children.Property2"));
pl.Add(Projections.GroupProperty("children.Property2"));
pl.Add(Projections.GroupProperty("entity.Id"));
return criteria.SetProjection(pl)
.SetFirstResult(actualPage * numberOfRecordsPerPage)
.SetFetchSize(numberOfRecordsPerPage)
.List<object>();
}
The drawback would be that your returned data are a list of arrays (you will have to cast object to object[]) but you can overcome that by using the AliasToBean functionality that lest NHibernate project these arrays to strongly typed objects that you define.
it's simple with CreateFilter
session.CreateFilter(entity.children, "")
.SetFirstResult(0)
.SetMaxResults(20)
.List();
http://knol.google.com/k/fabio-maulo/nhibernate-chapter-16/1nr4enxv3dpeq/19#

Using Criteria to get only base types

I'm looking for way in Fluent NHibernate to get a list of all object of type PARENT
using criteria.
I have a father object and a derived child.
The father contains a list of childs.
The problem is that when I use:
ICriteria crit = session.CreateCriteria(typeof(Parent))
IList<Parent> myRes = crit.List<Parnet>()
NH return back the list of both parent elements and the derived children elements, which is "right" b/c that is what I've asked, but that is not what I need.
(the children elements should be only inside the father object, but since they are of type parent as well - since they derived from it... NH brings them as well using this method.)
How can I get the list of all my "father" elements without the derived children ?
This is from the first answer (#Stefan Steinegger's)
session
.CreateQuery("from Parent where Parent.class == :class")
.AddType(typeof(Parent));
It looks like I need something like that - but it doesn't work in Fluent NHibernate.
Thanks,
Dani
the question actually is: how do you determine if a Parent is a root parent? there are various approaches:
You keep your model and define: a root is a Parent that is not inherited and is not included in any other Parent.
The part "is not inherited" might be easy to determine, but is actually a poor definition. When using inheritance, you should actually not care if an object you get as a certain type is actually inherited or not, this is the nature of inheritance.
The part "is not included in any other Parent" is hard to find out in an efficient way.
You set a reference to an objects parent. A root is a Parent where its parent references null.
You derive your Root from a common Base class. A Child is not a Root anymore, and a Root is a Root.
I suggest to take the last option.
BTW: you can filter for the exact type, but only using HQL.
session
.CreateQuery("from Parent where Parent.class == :class")
.AddType(typeof(Parent));