About relations

Jun 5, 2012 at 3:44 PM


I have a question about working relationships:

if I have a table named OrderDN, containing a MList<OrderLineDN>, which in turn has a property of type ProductDN, how can I write a property in ProductDN that returns a list of OrderDN related?

in other words, how can I have a EntityList of Orders in the Product UserControl?


Jun 6, 2012 at 7:48 AM
Edited Jun 6, 2012 at 7:51 AM

From a relational point of view. OrderLine is a relational table betweeen OrderDN and ProductDN, so far so good. But Signum Framework has a non-symmetrical approach between DB relationthips. 

On one side, you have OrderDN witch have an MList<OrderLineDN>, on the windows side this means using an EntityList or manually binding the data to some kind of ListView. The point is that, when you save the Order the OrderLines get updated. The OrderLineDN belong to OrderDN. 
On the other side, you have products. For statistical purposes it makes sense to see witch OrderLineDN are related to this Product, but it doesn't make sense to add an OrderLineDN from there. 

In order to make this reverse relationship on the user interface, you need to use an embedded search control. (http://www.signumframework.com/Search.ashx#SearchControl). Depending on your purposes, you can associate it with a query of OrderLineDN.

 	<m:SearchControl QueryName="{x:Type d:OrderLineDN}" x:Name="sc">
                <m:FilterOptions ColumnName="Product" Operation="EqualTo" Value="{Binding DataContext, ElementName=sc}"/>

Or just orders using a more complex QueryToken. 

 	<m:SearchControl QueryName="{x:Type d:OrderDN}" x:Name="sc">
                <m:FilterOptions ColumnName="Entity.Lines.Any.Product" Operation="EqualTo" Value="{Binding DataContext, ElementName=sc}"/>

 Finally, if in your business logic you are going to use this reverse relationship often, its usually a good idea to represent it using an expressionMethod (http://www.signumframework.com/ExpressionTrees-Extensibility.ashx)

static Expression<Func<ProductDN, IQueryable<OrderDN>>> OrdersExpression =
    p => Database.Query<OrderDN>().Where(o => o.Details.Any(ol=>ol.Product.RefersTo(p));
public static IQueryable<OrderDN> Orders(this ProductDN p)
    return OrdersExpression.Evaluate(p);

Then you can make queries like


Finally, you can register this expression on the DynamicQueryManager, so it's available on the QueryTokenBuilder (for adding filters and columns on a SearchWindow).

dqm.RegisterExpression((ProductDN o)=>o.Orders());

Hope it helps.

Jun 6, 2012 at 1:26 PM

Hi Olmo,

thanks for the answer. I found the first method works for me.

 I tried instead to use the Expression Trees, but I have not figured out how results link to the SearchControl. Perhaps I'm missing some step.

Congratulations on the excellent work.

Jun 6, 2012 at 2:08 PM

The 'second method' is not an alternative, is complementary. 

By using expressionMethods you have a shortcut for writing this piece of query on your business logic. 

Additionally, you can register this expression on the DQM. So when adding complex filters it looks like a collection for the users. 

This will allow your users to set a filter on the Product search control like:

Entity.Orders.Any.Customer.Name = "John" 

But in your case, the SearchControl filter is all you need. 

Hope it helps 


Jun 8, 2012 at 11:02 AM

Hi Olmo,

I have another question about Expression Tree. In the documentation I have seen the Expression declared in the Entity assembly, but in your example you talk about Business Logic,or rather, a extension method of my entities (?).  In fact, I can not use the Database static class in my entity Assembly.

Jun 9, 2012 at 3:34 PM

Hi Olmo,

I've tried to set a filter as you wrote in your last post, and it work fine. Thanks.

Jun 10, 2012 at 10:48 AM
Sorry for the late answer.

Expression method/properties is a convention to make the body of the method understandable by the LINQ provider.

You can use this technique on any assembly, entities or logic, but inside of the method you should use only the available resources in order for the assembly to compile.

So, if the body needs access to the Database class, we make it an static extension expression method on the logic assembly. I.e: myCustomer.Orders()

If the body requires only local data, then we make it an instance expression property. I.e: myCustomer.IsAlive that depends only on myCustomer date of birth and defuntion.

Hope it helps