Problem with multiple instances of a nested component in an entity.

MylesRip's Avatar

MylesRip

18 May, 2010 03:02 PM via web

I'm using Automapping with build 677. I'm getting the error: "Invalid index N for this SqlParameterCollection with Count=N." The error is happening because of how two instances of nested components are mapped. I have two instances of a component that contains a property plus two other components. In the mapping, the component property that isn't nested gets a prefix (member name) appended to the column name, but the columns for the nested components' properties do not get a prefix. I end up with duplicate column names which cause the above error.
Is there a workaround for this?

  1. Support Staff 2 Posted by James Gregory on 18 May, 2010 03:04 PM

    James Gregory's Avatar

    Could you give me an example of your entities and any configuration you've done of the automapper? I'll investigate your issue later.

  2. 3 Posted by MylesRip on 18 May, 2010 04:19 PM

    MylesRip's Avatar

    Here is a simplified description:

    // entity
    public class ReallyLongItem : Item
    {
        private Location _ThisEnd;
        private Location _ThatEnd;
        ...
        public virtual Location ThisEnd   // first instance of Location
        {
            get { return _ThisEnd }
            set { _ThisEnd = value; }
        }
        public virtual Location ThatEnd   // second instance of Location
        {
            get { return _ThatEnd }
            set { _ThatEnd = value; }
        }
        public virtual string ItemId { get; set; }
    }
    
    // outer component
    public class Location : IEquatable<Location>
    {
        ...
        public virtual LocationFormatEnum Format { get; private set; }  
        public virtual FormatA FormatA { get; private set; }  // nested component instance
        public virtual FormatB FormatB { get; private set; }  // instance of a different nested component
        ...
    }
    
    // nested components
    public class FormatA : IEquatable<FormatA>
    {
        public virtual string PropertyA1 { get; private set; }
        public virtual string PropertyA2 { get; private set; }
    }
    
    public class FormatB : IEquatable<FormatB>
    {
        public virtual string PropertyB1 { get; private set; }
        public virtual string PropertyB2 { get; private set; }
    }
    

    And the columns produced from Automapping are:

    ThisEndFormat
    PropertyA1
    PropertyA2
    PropertyB1
    PropertyB2
    ThatEndFormat
    PropertyA1 (duplicate)
    PropertyA2 (duplicate)
    PropertyB1 (duplicate)
    PropertyB2 (duplicate)
    ItemId

    Here are the Automapper configuration overrides I'm using:

    public class CustomAutomappingConfiguration : DefaultAutomappingConfiguration
    {
        public override bool IsComponent(Type type)
        {
            return type == typeof(Location) || type == typeof(FormatA) || type == typeof(FormatB);
        }
    
        /// <summary>
        /// IsDiscriminated = "true" implies a "table per class hierarchy" approach in which a discriminator column is used.
        /// IsDiscriminated = "false" implies a "table per class" approach.
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public override bool IsDiscriminated(Type type)
        {
            return (type == typeof(Item) || type.IsSubclassOf(typeof(Item)));
        }
    
        public override bool ShouldMap(Type type)
        {
            return !type.ClosesInterface(typeof(IAutoMappingOverride<>)) &&
                !type.HasInterface(typeof(IMappingProvider)) &&
                type.Namespace.EndsWith("DomainModel.Entities");
        }
    }
    

    Please let me know if you need additional information. Thanks!

  3. 4 Posted by MylesRip on 18 May, 2010 06:32 PM

    MylesRip's Avatar

    I just noticed something that I should help to solve this issue!

    I have mapping overrides for both the FormatA and FormatB nested components which I use to override the string length. For example:

    mapping.Map(x => x.PropertyA1).Length(2);
    

    If I comment out the previous line, the field maps to the column "FormatAPropertyA1". When it is not commented out, it maps to "PropertyA1".

    By simply trying to override the string length, the column name mapping behavior is changed.

    Of course what I really need is for it to map to "ThisEndFormatAPropertyA1" representing the multiple levels of nesting. ;-)

    Hopefully the above information will help to track down the source of the behavior.

    ( I tried using a fluent mapping to override the automapping and set the column name for a specific instance of the component, but although the fluent mapping is executed, the column name override is ignored. That is covered in a separate discussion. )

  4. Support Staff 5 Posted by James Gregory on 18 May, 2010 06:52 PM

    James Gregory's Avatar

    Thanks for the extra info, I'll investigate when I get home tonight.

  5. Support Staff 6 Posted by James Gregory on 20 May, 2010 03:40 AM

    James Gregory's Avatar

    Alright, this issue should be fixed if you get the latest version. Our automapping code that dealt with the column prefixing was naive and didn't consider nested components; it's now a lot more robust.

  6. 7 Posted by MylesRip on 20 May, 2010 05:13 PM

    MylesRip's Avatar

    Beautiful! I just tried build 1.0.0.680 and it completely resolved this issue. I was able to remove the overrides I was using to get around it. I'm sure this will avert some headaches for quite a few people. :-) Great job! FNH rocks!!

  7. Support Staff 8 Posted by James Gregory on 20 May, 2010 05:23 PM

    James Gregory's Avatar

    Great, glad to hear it!

  8. James Gregory resolved this discussion on 20 May, 2010 05:23 PM.

Comments are currently closed for this discussion. You can start a new one.