Home
Help
Register
Log in

Search

 
   Active Threads  

You are here: Home > LLBLGen Pro > Bugs & Issues> Navigator to subtyped relation table
 

Pages: 1
Bugs & Issues
Navigator to subtyped relation table
Page:1/1 

  Print all messages in this thread  
Poster Message
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
149 posts
# Posted on: 04-Jul-2020 18:20:37.  
v.5.5.3 Adapter, MSSQL, DB first

I have tables:
Defect
PartyRole and its subtype ProductionUnit

Then I have relationship table Defect2PartyRole
This table is subtyped to Defect2ProductionUnit, Defect2Customer ...

I have two Devex grids on form.
GridMaster datasource=Defects collection
GridChild datasource=Defect collection, datamember=

I need to set GridChild datamember to Defect2PartyRole subtype: "Defect2ProductionUnit"
but only "Defect2PartyRoles" is available as a choice in winforms designer.

In LLBL designer Defect entity has only navigator to supertype "Defect2PartyRoles"

I tried to add relationship in LLBL designer from DefectEntity to Defect2ProductionUnit, but designer shows warning DZ0040 that new relationship is shared with Defect<->Defect2PartyRoles relationship. And DZ0025 warning about missing foreign backing key constraint in DB...

As LLBL designer knows Defect2ProductionUnit is subtype of Defect2PartyRole, why it cannot automatically create also navigators to subtypes?
This way DefectEntity will have subcollections "Defect2PartyRoles" and also "Defect2ProductionUnit" and easy to set GridChild datamember to Defect2ProductionUnit
  Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
38047 posts
# Posted on: 05-Jul-2020 09:29:01.  
A navigator of type T is able to provide types T and all subtypes of T, that's how inheritance works, as you know. The designer doesn't create navigators for subtypes as it's unnecessary: the navigator that's there is capable of returning the subtypes. Remember, the navigator is mapped onto a relationship between the supertype and another entity, so all subtypes of that supertype apply. Adding another navigator is nothing more than a readonly filter on the already existing one.

the winforms designer here shows the type of the navigator. If you want to show a specific grid for a specific type, you have to define multiple grids and view them based on the data, i.e. make all of them hidden and show the one that applies.

If I have Customer - Orders and Order is a supertype of 2 different order types, O1 and O2, even with 2 navigators it won't help: I would have to make the selection at runtime in a small piece of code to decide which grid is visible: the grid viewing the columns for O1 or the grid viewing the columns of O2. If I recall correctly, you can do that in the same grid control with different views. (but it requires a bit of code).


Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
149 posts
# Posted on: 05-Jul-2020 11:35:01.  
This is especially databinding issue. Based on navigators, datamember is generated (related collection)

Say I have Customer - Orders and Order is a supertype of 2 different order types, O1=PurchaseOrder and O2=SalesOrder

I load Customer collection with prefetch to Orders even with typefilter to subtype CustomerPurchaseOrder

I will add two Devex grids to form:
1/ GridCustomer
datasource=Customer collection

2/ GridPurchaseOrders (O1);
datasource=Customer collection
datamember=CustomerOrders <- I cannot select DataGrid DataMember property=CustomerPurchaseOrder, as navigator is only to supertype CustomerOrders, means datamember can be set only to CustomerOrders.

This way I will no see specific fields for subtype CustomerPurchaseOrders
If I add new row in grid, the type of row is automatically CustomerOrderEntity
Thus when Customer entity is saved with recurse=true, it will fail as it will write only to CustomerOrder table, not also to CustomerPurchaseOrders inherited table.

The only workaround now for this scenario is not use prefetch, load Customer collection without related entities, then load CustomerPurchaseOrders as collection.
And then write some databinding hacks, when Customer current is changed then set filter to CustomerPurchaseOrder collection... Also saving has to be done separately, cannot be saved as graph by SaveEntity.

PS: Use more views in the same Devex grid does not solve this, as datamember datatype will be CustomerOrder ...

https://supportcenter.devexpress.com/ticket/details/e883/how-to-display-master-detail-tables-in-separate-grid-controls
  Top
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
149 posts
# Posted on: 05-Jul-2020 18:24:48.  
There will be in CustomerEntity code like:
Code:

<TypeContainedAttribute(GetType(CustomerOrderEntity))> _
Public Overridable ReadOnly Property [CustomerOrder]() As EntityCollection(Of CustomerOrderEntity)
    Get    
        Return GetOrCreateEntityCollection(Of CustomerOrderEntity, CustomerOrderEntityFactory)("Customer", True, False, _customerOrder)
    End Get
End Property


Seems in order to see/set datamember=CustomerPurchaseOrder I have to add into CustomeEntity something like:

Code:

<TypeContainedAttribute(GetType(CustomerPurchaseOrderEntity))> _
Public Overridable ReadOnly Property [CustomerPurchaseOrder]() As EntityCollection(Of CustomerPurchaseOrderEntity)
    Get
        ???? what should be there <<<<<-
    End Get
End Property


Seems the "only" remaining problem is how to bind that to DataGrid, so when adding new rows in grid then databinding will add rows into Customer.PurchaseOrders collection



  Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
38047 posts
# Posted on: 06-Jul-2020 10:44:39.  
the problem is that a 'collection' property is a set of a given type. If that type has subtypes, it can contain instances of that subtype but it can't be expressed in the type of the property. That's the case with all inheritance. You want to have exactly that: 1 type which can reflect exactly what types are in the collection, but that's not possible.

You can utilize contravariance, altho I'm not sure if VB.NET supports that. You have to cast to IEnumerable<CustomerOrderEntity> first:

Code:
public class Customer
{
    public List<Order> Orders {get;set;}
    
    public IEnumerable<POrder> PurchaseOrders
    {
        get { return (IEnumerable<POrder>)(IEnumerable<Order>)this.Orders; }
    }
}

public class Order
{
}

public class POrder
{
}

public class TOrder
{
}


See: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/covariance-contravariance/

Downside is that an IEnumerable is readonly. So to add new rows, I think it's best to bind a collection of the actual type, which you fetch separately. This makes databinding easy, and you can use databinding to set the parent / FK field with the selected customer's pk for new entities. To persist both you can just use a Unit of work.
Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
Rosacek
User



Location:
CZ
Joined on:
18-Mar-2012 18:02:44
Posted:
149 posts
# Posted on: 06-Jul-2020 14:58:29.  
Thanks Otis!

Finally I solved it simply.
I added manually relationship "CustomerPurchaseOrders", check ModelOnly checkbox.
And changed prefetch to this relationship and everything works.

The only obvious "problem" is this relationship duplicates inherited relationship so I can see warning DZ0040 ...
Quote:
The Foreign Key field '... (FK)' in the relationship '....' is shared with the relationship ..., and it therefore has multiple sources of truth. You should re-model this so FK fields aren't shared among relationships.


But I can live with that Cool

Have to say again: perfect product & perfect support.


  Top
Otis
LLBLGen Pro Team



Location:
The Hague, The Netherlands
Joined on:
17-Aug-2003 18:00:36
Posted:
38047 posts
# Posted on: 07-Jul-2020 09:11:13.  
Laugh Glad you found a solution for this problem Regular Smiley
Frans Bouma
LLBLGen Pro / ORM Profiler Lead Developer | Blog | Twitter
 
Top
Pages: 1  


Powered by HnD ©2002-2007 Solutions Design
HnD uses LLBLGen Pro

Version: 2.1.12172008 Final.