missing: support for navigation-properties on components
missing: support for navigation-properties on components
Somewhat shockingly, I just realized that all navigation-properties from my existing imported NHibernate mapping files were discarded on import!
And then furthermore, I discovered that relations between entities and components don't seem to be supported by ED at all?
I have one entity with around 240 properties in about 10 different components, and this is all pre-existing code and tables, so there really is no way around this - I have to map these as components.
Having this many properties on one entity is not generally my cup of tea, but my client really needs to record over 200 different properties on this one entity - and all of them need to be queryable, and the queries need to run fast, so there was no good way to avoid this...
I'm almost 100 hours into porting a huge data-model to ED, we've purchased the software, and I'm almost done. I should have realized early on that this feature was unsupported, but you do advertise support for "all kinds of mappings", which I took as meaning all kinds of mappings supported by NH.
It never occurred to me that these properties were missing - the HBM importer did not notify me that anything was being discarded during import.
Any chance this feature will be added in the near future?
And then furthermore, I discovered that relations between entities and components don't seem to be supported by ED at all?
I have one entity with around 240 properties in about 10 different components, and this is all pre-existing code and tables, so there really is no way around this - I have to map these as components.
Having this many properties on one entity is not generally my cup of tea, but my client really needs to record over 200 different properties on this one entity - and all of them need to be queryable, and the queries need to run fast, so there was no good way to avoid this...
I'm almost 100 hours into porting a huge data-model to ED, we've purchased the software, and I'm almost done. I should have realized early on that this feature was unsupported, but you do advertise support for "all kinds of mappings", which I took as meaning all kinds of mappings supported by NH.
It never occurred to me that these properties were missing - the HBM importer did not notify me that anything was being discarded during import.
Any chance this feature will be added in the near future?
Our investigation is in progress and we need more information:
1) Please specify which kind of mapping you need in more details. As we understood, you need support for Collections of dependent objects, which are described in the 7.2 paragraph of NHibernate Reference Documentation ?
2) Please describe your model in more details: if there are connected entities in the model, etc. If possible, please send us your model or the part of it that contains objects and a sample of the required mapping.
1) Please specify which kind of mapping you need in more details. As we understood, you need support for Collections of dependent objects, which are described in the 7.2 paragraph of NHibernate Reference Documentation ?
2) Please describe your model in more details: if there are connected entities in the model, etc. If possible, please send us your model or the part of it that contains objects and a sample of the required mapping.
Yes, exactly that - what you referenced in paragraph 7.2 of the documentation:
The many-to-one on the Purchase composite currently cannot be modeled - and the same of course for many-to-many mappings on a composite.
In my existing application, a number of components have properties with varying collection types. I don't think you would gain anything from seeing my code - it's similar to the example you mentioned.
Navigation properties on components, as far as I understand, have all of the same capabilities as navigation-properties on any other entity - from NHibernate's perspective, they are pretty much treated the same. The mappings of course are nested differently, but are otherwise the same, as far as I understand...
Code: Select all
<class name="Order" .... >
....
<set name="PurchasedItems" table="purchase_items" lazy="true">
<key column="order_id">
<composite-element class="Purchase">
<property name="PurchaseDate"/>
<property name="Price"/>
<property name="Quantity"/>
<many-to-one name="Item" class="Item"/> <!-- class attribute is optional -->
</composite-element>
</set>
</class>
In my existing application, a number of components have properties with varying collection types. I don't think you would gain anything from seeing my code - it's similar to the example you mentioned.
Navigation properties on components, as far as I understand, have all of the same capabilities as navigation-properties on any other entity - from NHibernate's perspective, they are pretty much treated the same. The mappings of course are nested differently, but are otherwise the same, as far as I understand...
The feature is available in the latest 4.2.120 build of Entity Developer.
The new build can be downloaded from http://www.devart.com/entitydeveloper/download.html (the trial and free versions) or from Registered Users' Area (provided that you have an active subscription).
For more information, please refer to http://www.devart.com/forums/viewtopic.php?t=23252 .
The new build can be downloaded from http://www.devart.com/entitydeveloper/download.html (the trial and free versions) or from Registered Users' Area (provided that you have an active subscription).
For more information, please refer to http://www.devart.com/forums/viewtopic.php?t=23252 .
Just installed 4.2.120 (27-Jan-2012) and I don't see this feature?
Checked my about box and it says 4.2.120 after install.
My guess was you would right-click a component and select "Add Assocation", same as for classes - but all I see is "Add Property", and nothing new in the property dialog.
How do I access this feature?
Checked my about box and it says 4.2.120 after install.
My guess was you would right-click a component and select "Add Assocation", same as for classes - but all I see is "Add Property", and nothing new in the property dialog.
How do I access this feature?
The "Add Association" command in the shortcut menu is unavailable for complex types because in fact a class contains a collection of complex types. And a complex type conceptually is not related with a class or an association.
Thats why you need to right-click the corresponding class an select "Add Association" from the shortcut menu, then select the corresponding complex type in the "Class" combobox for the End2 , and then set other association parameters.
Thats why you need to right-click the corresponding class an select "Add Association" from the shortcut menu, then select the corresponding complex type in the "Class" combobox for the End2 , and then set other association parameters.
That seems odd, why wouldn't I be able to create this relationship from either one end or the other, same as any other relationship?
Complex types may not be conceptually related with classes in your software - but in design terms, and in terms of NH support for these patterns, an entity (class) and a complex type (component) really aren't any different at all - they're just located in different places in the object model graph. They're both just objects of a given type.
To prove my point - NH actually permits you to map the same type in both ways. So for example, Address might be mapped as an entity to a table in one situation, and used as a component (mapped to columns on another entity) in another situation.
Having a strict separation between so-called complex types and classes really isn't very meaningful, in my opinion. For instance, a competing product, NHibernate Designer doesn't make this distinction - types are just types, whereas there are multiple types of associations, which determine how the mappings are actually implemented. This is how models are generally documented using standard UML class diagrams/tools as well - the arrows define the kind of relationship one type has with another; there's only kind of "type".
I realize that's just a different way to look at things, and you chose a different approach - all I'm saying is, this model more accurately resembles the traditional relational model, as implemented by various standards, such as UML class diagrams.
Anyway, some more practical notes...
I didn't notice that complex types are now listed on the drop-down, because the drop-down is not longer alphabetized.
Also, selecting a complex type from the dropdown pops up an error message saying "Cannot uncheck both Generate properties", although "Generate related property" is checked for End 1.
Navigation properties also aren't displayed on complex types.
It looks like you normalized some of the common features between classes and complex types by adding an interface? It still looks to me as if classes and complex types have more in common - in fact, they should be largely the same, and the workflow definitely would be more streamlined if they behaved the same way in the user-interface.
The terminology itself is kind of "off" - you have something called a "class", and another thing called a "complex type", but complex types really are just classes with a different purpose. But they're still classes. I'm not sure treating them as something fundamentally different is really the right way to go...
Complex types may not be conceptually related with classes in your software - but in design terms, and in terms of NH support for these patterns, an entity (class) and a complex type (component) really aren't any different at all - they're just located in different places in the object model graph. They're both just objects of a given type.
To prove my point - NH actually permits you to map the same type in both ways. So for example, Address might be mapped as an entity to a table in one situation, and used as a component (mapped to columns on another entity) in another situation.
Having a strict separation between so-called complex types and classes really isn't very meaningful, in my opinion. For instance, a competing product, NHibernate Designer doesn't make this distinction - types are just types, whereas there are multiple types of associations, which determine how the mappings are actually implemented. This is how models are generally documented using standard UML class diagrams/tools as well - the arrows define the kind of relationship one type has with another; there's only kind of "type".
I realize that's just a different way to look at things, and you chose a different approach - all I'm saying is, this model more accurately resembles the traditional relational model, as implemented by various standards, such as UML class diagrams.
Anyway, some more practical notes...
I didn't notice that complex types are now listed on the drop-down, because the drop-down is not longer alphabetized.
Also, selecting a complex type from the dropdown pops up an error message saying "Cannot uncheck both Generate properties", although "Generate related property" is checked for End 1.
Navigation properties also aren't displayed on complex types.
It looks like you normalized some of the common features between classes and complex types by adding an interface? It still looks to me as if classes and complex types have more in common - in fact, they should be largely the same, and the workflow definitely would be more streamlined if they behaved the same way in the user-interface.
The terminology itself is kind of "off" - you have something called a "class", and another thing called a "complex type", but complex types really are just classes with a different purpose. But they're still classes. I'm not sure treating them as something fundamentally different is really the right way to go...
I don't understand how this works.
I can only add the Association from the opposite side of the complex type, so I click on the other class, and select "Add Association".
Only "End 2" offers complex types in the Class drop-down, so I select the complex type from there.
At this point, I see a "Join Table" input, and all the properties of the complex type listed under "Composite element mapping" below, implying that a whole table is going to be generated to store instance of the complex type??
I don't understand what would be the point of this at all - you can already model the exact same thing by adding a normal class (rather than a complex type) and a relationship with another class.
I'm afraid what you've done is the exact opposite of what I was asking for?
It seems you have the ability to add many instance of a complex type as a collection on another class.
What I was looking for, was the ability to add navigation properties to complex types. I believe that's what the example you posted demonstrates:
What I'm looking for here, is the many-to-one - outgoing navigation from a property on a component, not the other way around.
Mapping "complex types" the way your new feature permits, comes back to my argument (above) that complex types really are just classes. Giving them special status means they need special treatment, but this type of mapping really was already possible, using a "class" rather than a "complex type"...
But maybe I have completely misunderstood how this works?
I looked in the documentation, but I don't see anything documenting how to configure navigation properties on complex types. Could you point out the right place to look, or maybe post an example or further explanation?
I can only add the Association from the opposite side of the complex type, so I click on the other class, and select "Add Association".
Only "End 2" offers complex types in the Class drop-down, so I select the complex type from there.
At this point, I see a "Join Table" input, and all the properties of the complex type listed under "Composite element mapping" below, implying that a whole table is going to be generated to store instance of the complex type??
I don't understand what would be the point of this at all - you can already model the exact same thing by adding a normal class (rather than a complex type) and a relationship with another class.
I'm afraid what you've done is the exact opposite of what I was asking for?
It seems you have the ability to add many instance of a complex type as a collection on another class.
What I was looking for, was the ability to add navigation properties to complex types. I believe that's what the example you posted demonstrates:
Code: Select all
<composite-element class="Purchase">
<property name="PurchaseDate"/>
<property name="Price"/>
<property name="Quantity"/>
<many-to-one name="Item" class="Item"/> <!-- here! -->
</composite-element>
Mapping "complex types" the way your new feature permits, comes back to my argument (above) that complex types really are just classes. Giving them special status means they need special treatment, but this type of mapping really was already possible, using a "class" rather than a "complex type"...
But maybe I have completely misunderstood how this works?
I looked in the documentation, but I don't see anything documenting how to configure navigation properties on complex types. Could you point out the right place to look, or maybe post an example or further explanation?
Sorry for mass posting here.
I created an example to illustrate the need and the problem, plus another problem I ran into while creating this example.
Here's a sample project:
https://docs.google.com/open?id=0BxKmkm ... k0ZmVhZjE2
First off, try to generate the schema - it won't work. Clearly there is some kind of checking here that doesn't work like it's supposed to - the BillingAddress and ShippingAddress properties have different prefixes, so they don't really overlap, but the error message says they do.
This is the second problem, which is unrelated to the problem I'm trying to demonstrate. To work around the second problem, for now just delete the ShippingAddress property.
The following schema is generated:
The first problem is this: the Address component needs a Country navigation property, associated with the Country type on the diagram.
So in terms of schema, I would expect to see a Billing_CountryId column on the table Customers.
I don't think what you implemented allows me to do that?
I created an example to illustrate the need and the problem, plus another problem I ran into while creating this example.
Here's a sample project:
https://docs.google.com/open?id=0BxKmkm ... k0ZmVhZjE2
First off, try to generate the schema - it won't work. Clearly there is some kind of checking here that doesn't work like it's supposed to - the BillingAddress and ShippingAddress properties have different prefixes, so they don't really overlap, but the error message says they do.
This is the second problem, which is unrelated to the problem I'm trying to demonstrate. To work around the second problem, for now just delete the ShippingAddress property.
The following schema is generated:
Code: Select all
CREATE TABLE dbo.Countries (
Id INT NOT NULL IDENTITY,
Name VARCHAR(MAX) NOT NULL,
CONSTRAINT PK_Countries PRIMARY KEY (Id)
)
GO
CREATE TABLE dbo.Customers (
Id INT NOT NULL IDENTITY,
Name VARCHAR(MAX) NOT NULL,
Billing_Street VARCHAR(MAX) NOT NULL,
Billing_City VARCHAR(MAX) NOT NULL,
CONSTRAINT PK_Customers PRIMARY KEY (Id)
)
GO
So in terms of schema, I would expect to see a Billing_CountryId column on the table Customers.
I don't think what you implemented allows me to do that?
We will change the sort order in the "Class" drop-down for the "End 2" in the Association Editor.mindplay wrote: I didn't notice that complex types are now listed on the drop-down, because the drop-down is not longer alphabetized.
Thank you for the report, we have reproduced the problem.mindplay wrote: Also, selecting a complex type from the dropdown pops up an error message saying "Cannot uncheck both Generate properties", although "Generate related property" is checked for End 1.
We will fix it and inform you when the corresponding build is available.
We have fixed the bug with script generation when there is an entity in the model that has several complex type properties of the same complex type.mindplay wrote: First off, try to generate the schema - it won't work. Clearly there is some kind of checking here that doesn't work like it's supposed to - the BillingAddress and ShippingAddress properties have different prefixes, so they don't really overlap, but the error message says they do.
A component is a contained object that is persisted as a value type, not an entity.mindplay wrote: Navigation properties also aren't displayed on complex types.
Components cannot have navigation properties, that's why there no navigation properties in complex types on a diagram. Only an entity can contain a collection of components.
If you don't want to use all the table columns, but only part of the table, you may create a complex type (component) with the properties you want to retrieve from the table, and create an association to this complex type and specify the table name and foreign key columns in the association settings . It does not differ much from creating association between two entities. The difference is that table is partially mapped to the component, instead of being mapped entirely to the entity. This component does not have and cannot have the reference to the entity, - the entity will have a collection of the components.
"Composite elements may contain components but not collections" ( see http://www.nhforge.org/doc/nh/en/index. ... ollections). Besides, the same section says: "A special case of a composite element is a composite element with a nested element. A mapping like this allows you to map extra columns of a many-to-many association table to the composite element class".
I.e. when creating a many-to-many association, if the join table (the one that connects two tables that corresponds to the ends of the association) contains additional columns (not just foreign key columns), you may use component to retrieve them. In this case a complex type, having the properties we want to retrieve, is created and specified in the Component box of the Association Editor for the many-to-many association. In the generated code, the classes, corresponding to the entities on the ends of this many-to-many association, will have the collections of complex types, containing the properties, corresponding to the additional columns of the join table, and the reference to the opposite entity class. NHibernate does not have other ways to use the collections of dependent objects. It's impossible to create the mapping you've described, NHibernate does not allow it.
If you want, we can send you Entity Developer models, which demonstrate the features, related to the collections of dependent objects, that are supported in NHibernate.
Yes, but that's not what I'm asking for - I realize you can't have collections of objects attached to a component, but that's not what I'm trying to do.Components cannot have navigation properties, that's why there no navigation properties in complex types on a diagram. Only an entity can contain a collection of components.
Here's an excerpt of the mappings in my existing project - this is a functioning mapping:
Code: Select all
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="MyApp.Entities.Location" table="Location">
<id name="Id" type="System.Int32" unsaved-value="0">
<column name="Id" />
<generator class="identity" />
</id>
<property name="Name" type="System.String">
<column name="Name" length="120" not-null="true" />
</property>
<component name="CustomerFinance" insert="true" update="true" optimistic-lock="true" class="MyApp.Entities.LocationFinance">
<property name="TaxPayerId" type="System.String">
<column name="CustomerFinance_TaxPayerId" length="50" />
</property>
<many-to-one cascade="none" class="MyApp.Entities.Country" name="Country">
<column name="CustomerFinance_CountryId" />
</many-to-one>
</component>
<component name="VendorFinance" insert="true" update="true" optimistic-lock="true" class="MyApp.Entities.LocationFinance">
<property name="TaxPayerId" type="System.String">
<column name="VendorFinance_TaxPayerId" length="50" />
</property>
<many-to-one cascade="none" class="MyApp.Entities.Country" name="Country">
<column name="VendorFinance_CountryId" />
</many-to-one>
</component>
</class>
This is similar to the example I posted above, and the example you posted ealier from the documentation.
It's equivalent to the second example in the documentation reference you just posted - the "special case" mentioned is what I'm looking for.
Currently, I would have to put these country references as properties on the Location type, but then what's the point of using components to begin with? This doesn't give me any uniform way to program against these component instances, because the information they will carry with them is going to be incomplete, which would complicate everything from business logic down to controllers through to view-models.
If ED isn't going to support this mapping-feature, I will have to write and maintain these mappings by hand - this particular table, classes and mappings consists of over 240 properties, so you can see why I'm trying to avoid this...
The "special case" describes working with component's navigation properties in case of many-to-many association, but not with component property includes navigation property to another entity.mindplay wrote:It's equivalent to the second example in the documentation reference you just posted - the "special case" mentioned is what I'm looking for.
Your code sample considerably differs from the one we have discussed before:mindplay wrote:Here's an excerpt of the mappings in my existing project - this is a functioning mapping..
Helen wrote:1) Please specify which kind of mapping you need in more details. As we understood, you need support for Collections of dependent objects, which are described in the 7.2 paragraph of NHibernate Reference Documentation
We will investigate the possibility of implementing this mapping-feature (which are described in the 5.1.13 paragraph of NHibernate Reference Documentation) in Entity Developer.mindplay wrote:Yes, exactly that - what you referenced in paragraph 7.2 of the documentation.