Grails many to many with 3 classes: sorting by the number of relationships - sorting

Let's say we have 3 domain classes: 2 classes related with each other through a 3rd class.
Ok, some code:
class A {
String subject
String description
static hasMany = [cs: C]
static transients = ['numberOfCs']
Long getNumberOfCs() {
return cs.size()
}
}
class B {
String title
}
class C {
A objectA
B objectB
static belongsTo = [a: A]
}
Pretty clear? I hope so. This work perfectly with my domain.
You can see the transient property numberOfCs, which is used to calculate the number of C instances related to my A object. And it works just fine.
The problem: listing all my A objects, I want to sort them by the number of relationships with C objects, but the transient property numberOfCs cannot be used for the scope.
How can I handle the situation? How can I tell GORM to sort the As list by numberOfCs as it would be a regular (non transient) field?
Thanks in advance.

I'm not sure that Grails' criteria do support this, as you need both to select the A object itself and aggregate by a child objects (C). That means grouping by all the A's fields, which is not done automatically.
If you only need some fields from A, you can group by them:
def instances = A.withCriteria {
projections {
groupProperty('subject')
count('cs', 'cCount')
}
order 'cCount'
}
otherwise you'll need to retrieve only ids and make a second query, like in this question.
Another way is to use derived properties like described here (not sure it will work though):
class A {
static mapping = {
numberOfCs formula: 'select count(*) from C where c.b_id = id'
}
}

I wouldn't consider your Problem GORM related but rather general Hibernate or even SQL related.
Take a look at the HQL Docu they are a lot of examples.
check the following HQL this pretty close what you are asking.
select mySortedAs from A mySortedAs left join mySortedAs.cs myCsOfA order by
count(myCsOfA)
I think I saw somewhere that you also can do something like this myCsOfA.length or myCsOfA.size

Related

Grail domain model associations default sorting on multiple fields

Ive searched around for a solution on sorting an domain models association on multiple field but not found a single answer.
Is this not feature not yet implemented and in that case is there a 'good' workaround
I have two models:
Board{
static hasMany = [tiles: Tile]
static mapping = {
This is what i would like to do!!
sort x : 'asc'
sort y : 'acs'
}
}
Tile {
int x
int y
}
I am unable if there is a sorting built into the mapping. I been working with Grails for almost 3 years, and have not seen that yet. But i think the easier way to do that is try using collection sort, and Title implements comparable. And you do a Collection.sort(tiles);

Changing values of an object in a LINQ-statement

I want to add some calculated properties to an EntityObject without loosing the possibility of querying it agains the database.
I created a partial class and added the fields I need in the object. Than I wrote a static function "AttachProperties" that should somehow add some calculated values. I cannot do this on clientside, since several other functions attach some filter-conditions to the query.
The functions should look like this:
return query.Select(o =>
{
o.HasCalculatedProperties = true;
o.Value = 2;
return o;
});
In my case the calculated value depends on several lookups and is not just a simple "2". This sample works with an IEnumerable but, of course, not with an IQueryable
I first created a new class with the EntityObject as property and added the other necessary fields but now I need this extended class to be of the same basetype.
First, in my opinion changing objects in a Select() is a bad idea, because it makes something else happen (state change) than the method name suggests (projection), which is always a recipe for trouble. Linq is rooted in a functional programming (stateless) paradigm, so this kind of usage is just not expected.
But you can extend your class with methods that return a calculation result, like:
partial class EntityObject
{
public int GetValue()
{
return this.MappedProp1 * this.MappedProp2;
}
}
It is a bit hard to tell from your question whether this will work for you. If generating a calculated value involves more than a simple calculation from an object's own properties it may be better to leave your entities alone and create a services that return calculation results from an object graph.
Try something like this:
return from o in collection
select new O()
{
OtherProperty = o.OtherProperty,
HasCalculatedProperties = true,
Value = 2
};
This will create a copy of the original object with the changes you require and avoid all the messiness that come with modifying an entity in a select clause.

Entity Framework, Table Per Type and Linq - Getting the "Type"

I have an Abstract type called Product, and five "Types" that inherit from Product in a table per type hierarchy fashion as below:
I want to get all of the information for all of the Products, including a smattering of properties from the different objects that inherit from products to project them into a new class for use in an MVC web page. My linq query is below:
//Return the required products
var model = from p in Product.Products
where p.archive == false && ((Prod_ID == 0) || (p.ID == Prod_ID))
select new SearchViewModel
{
ID = p.ID,
lend_name = p.Lender.lend_name,
pDes_rate = p.pDes_rate,
pDes_details = p.pDes_details,
pDes_totTerm = p.pDes_totTerm,
pDes_APR = p.pDes_APR,
pDes_revDesc = p.pDes_revDesc,
pMax_desc = p.pMax_desc,
dDipNeeded = p.dDipNeeded,
dAppNeeded = p.dAppNeeded,
CalcFields = new DAL.SearchCalcFields
{
pDes_type = p.pDes_type,
pDes_rate = p.pDes_rate,
pTFi_fixedRate = p.pTFi_fixedRate
}
}
The problem I have is accessing the p.pTFi_fixedRate, this is not returned with the Products collection of entities as it is in the super type of Fixed. How do I return the "super" type of Products (Fixed) properties using Linq and the Entity Framework. I actually need to return some fields from all the different supertypes (Disc, Track, etc) for use in calculations. Should I return these as separate Linq queries checking the type of "Product" that is returned?
This is a really good question. I've had a look in the Julie Lerman book and scouted around the internet and I can't see an elegant answer.
If it were me I would create a data transfer object will all the properties of the types and then have a separate query for each type and then union them all up. I would insert blanks into the DTO properies where the properties aren't relevant to that type. Then I would hope that the EF engine makes a reasonable stab at creating decent SQL.
Example
var results = (from p in context.Products.OfType<Disc>
select new ProductDTO {basefield1 = p.val1, discField=p.val2, fixedField=""})
.Union(
from p in context.Products.OfType<Fixed>
select new ProductDTO {basefield1 = p.val1, discField="", fixedField=p.val2});
But that can't be the best answer can it. Is there any others?
So Fixed is inherited from Product? If so, you should probably be querying for Fixed instead, and the Product properties will be pulled into it.
If you are just doing calculations and getting some totals or something, you might want to look at using a stored procedure. It will amount to fewer database calls and allow for much faster execution.
Well it depends on your model, but usually you need to do something like:
var model = from p in Product.Products.Include("SomeNavProperty")
.... (rest of query)
Where SomeNavProperty is the entity type that loads pTFi_fixedRate.

Can LINQ ToArray return a strongly-typed array in this example?

I've contrived this example because it's an easily digested version of the actual problem I'm trying to solve. Here are the classes and their relationships.
First we have a Country class that contains a Dictionary of State objects indexed by a string (their name or abbreviation for example). The contents of the State class are irrelevant:
class Country
{
Dictionary<string, State> states;
}
class State { ... }
We also have a Company class which contains a Dictionary of zero or more BranchOffice objects also indexed by state names or abbreviations.
class Company
{
Dictionary<string, BranchOffice> branches;
}
class BranchOffice { ... }
The instances we're working with are one Country object and an array of Company objects:
Country usa;
Company companies[];
What I want is an array of the State objects which contain a branch. The LINQ I wrote is below. First it grabs all the companies which actually contain a branch, then joins to the list of states by comparing the keys of both lists.
The problem is that ToArray returns an anonymous type. I understand why anonymous types can't be cast to strong types. I'm trying to figure out whether I could change something to get back a strongly typed array. (And I'm open to suggestions about better ways to write the LINQ overall.)
I've tried casting to BranchOffice all over the place (up front, at list2, at the final select, and other less-likely candidates).
BranchOffice[] offices =
(from cm in companies
where cm.branches.Count > 0
select new {
list2 =
(from br in cm.branches
join st in usa.states on br.Key equals st.Key
select st.Value
)
}
).ToArray();
You can do:
select new MyClassOfSomeType {
..
)
For selection, you can give it a custom class type. You can also then use ToList. With ArrayList, if you need to keep it loosely typed, you can then make it strongly typed later using Cast<>, though only for any select result that doesn't generate an anonymous class.
HTH.
If i understand the problem correctly, the you want just the states that have office brances in them, not the branches too. If so, one posible linq is the following:
State[] offices =
(from cm in companies
where cm.branches.Count > 0
from br in cm.branches
join st in usa.states on br.Key equals st.Key
select st.Value
).Distinct().ToArray();
If you want both the states and the branches, then you will have to do a group by, and the result will be an IEnumerable>, which you can process after.
var statesAndBranches =
from cm in companies
where cm.branches.Count > 0
from br in cm.branches
join st in usa.states on br.Key equals st.Key
group br.Value by st.Value into g
select g;
Just one more thing, even though you have countries and branches declared as dictionaries, they are used as IEnumerable (from keyValuePair in dictionary) so you will not get any perf benefit form them.

Linq: Polymophic entity fetch in select list

I want to do the following...
FROM o IN orders
SELECT new OrderContainer { Contact = (PostalContact) o.Contact }
So hopefully you can see that the order's 'Contact' will be of a derived type. Unfortunately however it doesn't seem to do a polymorphic fetch! Is there anyway of achieving this?
Cheers, Ian.
Try using the extention method .OfType()
from o in orders
select new OrderContainer { Contact = o.Contact.OfType<PostalContact>().FirstOrDefault() }
Edit:
a way to get the full object data, but i doubt that this is good enough for your needs.
from c in contacts.OfType<PostalContact>()
where c.Orders.Any(o=>o.Contact.Id == c.id)
select new OrderContainer { Contact = c }
on the other hand, if you set the base class (entity) to abstract, you may find that entity will load the full objects. but this is not recomended due to the queries that are generated. if you are looking into this you may want to look at (TPH) Table per Hierarchy for your contacts

Resources