1

I did try and use this question Setting up one to many relationship with Fluent Nhibernate as a basis but still having issues.

I have two classes - Contact and PostalAddress - A Contact can have many addresses. The thing is when it gets to a class a with PostalAddress it fails with

Invalid index 1 for this SqlParameterCollection with Count=1.

There is one address against that particular contact

Contact Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;

namespace YourLivesDataEngine.DataObjects
{
    [DataContract()]
    public class Contact
    {
        private String givenName;
        private String surname;
        private String middleName;
        public Contact()
        {
            Emails              = new List<EmailAddress>();
            Addresses           = new List<PostalAddress>();
            TelephoneNumbers    = new List<TelephoneNumber>();

            givenName           = String.Empty;
            surname             = String.Empty;
            middleName          = String.Empty;

            Id                  = Guid.NewGuid().ToString();
        }
        [DataMember]
        public virtual String Id { get; set; }
        [DataMember]
        public virtual DateTime LastUpdated { get; set; }
        [DataMember]
        public virtual String Network { get; set; }
        [DataMember]
        public virtual String NetworkId { get; set; }
        [DataMember]
        public virtual String Name { get; set; }
        [DataMember]
        public virtual String GivenName { get; set; }
        [DataMember]
        public virtual String Surname { get; set; }
        [DataMember]
        public virtual String MiddleName { get; set; }
        [DataMember]
        public virtual IList<EmailAddress> Emails { get; set; }
        [DataMember(Name="Addresses")]
        public virtual IList<PostalAddress> Addresses { get; set; }
        [DataMember]
        public virtual IList<TelephoneNumber> TelephoneNumbers { get; set; }


    }
}

PostalAddress Class

public class PostalAddress
{
    public PostalAddress()
    {
        Id = Guid.NewGuid().ToString();
    }
    [DataMember]
    public virtual String Id { get; set; }
    public virtual String Address { get; set; }
    public virtual String Owner { get; set; }
    public virtual String AddressType { get; set; }
    public virtual Contact Contact { get; set; }
}

And my Mappings

ContactMap

public class ContactMap : ClassMap<Contact>
{
    public ContactMap()
    {
        Table("tblContacts");
        Id(x => x.Id);
        Map(x => x.LastUpdated);
        Map(x => x.Network);
        Map(x => x.NetworkId);
        Map(x => x.Name);
        Map(x => x.GivenName);
        Map(x => x.Surname);
        Map(x => x.MiddleName);

        HasMany<PostalAddress>(x => x.Addresses)
            .Inverse()
            .KeyColumns.Add("Id", mapping => mapping.Name("Id"))
            .Cascade.SaveUpdate()
    }
}

PostalAddressMap

   public class PostalAddressMap 
        : ClassMap<PostalAddress>
    {
        public PostalAddressMap()
        {
            Table("tblPostalAddresses");
            Id(x => x.Id);
            Id(x => x.Address);
            Id(x => x.AddressType);
            Id(x => x.Owner);

            References(x => x.Contact)
                .Class<Contact>()
                .Column("Owner");

        }
    }

The code to save the Contact is

   public void Save ( Contact Contact )
    {
        try
        {
            using (ISessionFactory factory = CreateSessionFactory())
            {
                using (var session = factory.OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        // save the contact
                        session.Save(Contact);
                        transaction.Commit();

                    }
                }
            }
        }
        catch ( System.Exception e)
        {
            throw e;
        }
        finally
        {

        }

    }

I'm sure it is something to do with the way the mapping is set-up but cannot see it, while there are some contacts that do not have an address - some do so I should have at least some addresses.

Community
  • 1
  • 1
Paul S Chapman
  • 832
  • 10
  • 37
  • Have you verified your maps through the PersistenceSpecification tester? Dont have VS near me so the syntax might be off: https://gist.github.com/mxmissile/d81682def1d88a522767 – mxmissile Aug 27 '15 at 19:43
  • No - I just got rid of the error in the question by commenting out the line in the PostalAddressMap referring to owner. Now it is not writing the Id to the PostalAddress Record and so failing setting the Id to null - which is not allowed as it is a primary key - and therefore does not allow null. – Paul S Chapman Aug 27 '15 at 19:50
  • To start with, your `PostalAddressMap` is wrong, you are mapping properties as Id's. – mxmissile Aug 27 '15 at 19:59
  • But what would I change to fix it - I'm not sure, and only have had this as an issue when trying to relate two classes. – Paul S Chapman Aug 27 '15 at 20:03
  • Sorry - not noticed I'd used Id where I should use 'Map' but having changed that now getting Invalid index 4 for this SqlParameterCollection with Count=4. which happens to be the number of mapped properties in the PostalAddress - now not sure what I need to fix that. - thanks in advance – Paul S Chapman Aug 27 '15 at 20:08

1 Answers1

0

With some help from mxmissile have now fixed it.

Problems were all in the mapping of PostalAddress. First off I had made all the fields Id's - so changed the required properties to Map.

Then got the Invalid index 4 for this SqlParameterCollection with Count=4 error everytime I tried to save the addresses. This error is caused when a field is mapped twice. For this mapping it was the Owner which was mapped twice. It did not need to be listed in the Map - by commenting it out the application worked. The revised Mapping class is as follows;

public class PostalAddressMap 
    : ClassMap<PostalAddress>
{
    public PostalAddressMap()
    {
        Table("tblPostalAddresses");
        Id(x => x.Id);
        Map(x => x.Address);
        Map(x => x.AddressType);

        References(x => x.Contact)
            .Class<Contact>()
            .Column("Owner");

    }
}

Once those changes were made the application saved the Contacts and Addresses correctly.

Paul S Chapman
  • 832
  • 10
  • 37