We're updating the issue view to help you get more done. 

Component mapping without explicit column/table names causes column/table overlap

Description

(follow-up to NH-3114)

When attempting to create an entity which has two components of the same type but no explicit mention of column names in the mapping, the result is an overlap of the two columns (being put on with the same name). The same happens for collections inside those components, except that they end up in the same table.

Initially discovered during the analysis for NH-3114, I attempted to write some tests for this as well. But since this was more a coincidence rather than an actual use case (which also appears to not impact anyone out there so far by the lack of existing an issue report), I did not really invest too much time researching this further.

Relevant parts in all conciseness as follows:

Entities

1 2 3 4 5 6 7 8 9 10 11 public class Component { public string ComponentProperty { get; set; } public ICollection<string> ComponentCollection { get; set; } = new List<string>(); } public class Entity { public Guid Id { get; set; } public Component FirstComponent { get; set; } public Component SecondComponent { get; set; } }

Mapping

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var mapper = new ModelMapper(); mapper.Class<Entity>(rc => { rc.Id(i => i.Id, m => m.Generator(Generators.GuidComb)); rc.Component(p => p.FirstComponent, m => { m.Set(c => c.ComponentCollection, // table name omitted, expecting a reasonable default c => { }, c => c.Element()); // not specifying a column name here (and below) causes an insert failure during session.Flush m.Property(p => p.ComponentProperty); }); rc.Component(p => p.SecondComponent, m => { m.Set(c => c.ComponentCollection, // table name omitted, expecting a reasonable default c => { }, c => c.Element()); // not specifying a column name here (and above) causes an insert failure during session.Flush m.Property(p => p.ComponentProperty); }); });

Note that this is not specific to Mapping by-code, as the same mapping XML created here could've been written by hand and appears to be just as legal.

As a result, the following tables are created:

1 2 Entity (Id, ComponentProperty) ComponentCollection (component_key, id)

Both Entity.FirstComponent.ComponentProperty and Entity.SecondComponent.ComponentProperty are stored to/loaded from table Entity, column ComponentProperty.
Both Entity.FirstComponent.ComponentCollection and Entity.SecondComponent.ComponentCollection are stored to/loaded from table ComponentCollection.

It would be to be expected that at least one more (distinctly named) column is placed in the Entity table and yet another table would be created to hold the contents of the second component collection. Sane (or rather, predictable) names would probably prepend the component property name to make things a little more unique (similar to the fix added in which includes the parent path inside Mapping by-code to make sure mapping actions are applied to the correct target)

Environment

None

Status

Assignee

Unassigned

Reporter

Emanuel Wlaschitz