0

I'm using NHibernate in my C# website and am having trouble trying to get it to run since the addition of the PatientInformation domain and mapping. If someone can review the code below and point to the area that is wrong, I would really appreciate the help.

I've tried updating the PatientInformationMap to include the ID field, but it doesn't seem to help prevent the error from occuring. I've tried changing the many-to-many in the PatientInformationMap to HasManyToMany<Form> but the error persists.

Judging from what I have seen in other stackoverflow posts, there is something wrong in my mapping. I haven't seen any posts that aren't using that hbm file, and I don't even know what that is so I'm not sure how those posts would help me much.

**** I'm aware I'm at risk of being voted down because my question is similar to others', but I really don't see how something pertaining to an hbm file is helpful to my situation. Thanks in advance for answering instead of immediately trying to get this question removed.

Exception occurred getter of Form.PatientInformation

Object does not match target type.
at CommonSessionManager.UnbindCurrentSession() in \CommonSessionManager.cs:line 54
at CommonSessionManager.Application_EndRequest(Object sender, EventArgs e) in \CommonSessionManager.cs:line 25
at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

************* Mapping

public PatientInformationMap()
{
        Schema("FormsLibrary");
        Table("PatientInformation");
        Map(x => x.FullName);
        Map(x => x.DateOfBirth);
        Map(x => x.ContactAccount);

        HasManyToMany<PatientInformation>(x => x.Forms)
            .Schema("FormsLibrary")
            .Table("PatientInformationToForms")
            .ParentKeyColumn("PatientInformationID")
            .ChildKeyColumn("FormID")
            .LazyLoad()
            .Cascade.SaveUpdate();
    }
}


 public FormMap()
 {
        Schema("FormsLibrary");
        Table("Form");
        Map(x => x.Title);
        Map(x => x.Description);
        Map(x => x.FileName);
        Map(x => x.MembersOnly);
        Map(x => x.Status);
        Map(x => x.Active);
        Map(x => x.DisplayFileName);
        Map(x => x.LastModified);
        Map(x => x.CreatedDate);

        References(x => x.User, "UserID").LazyLoad();
        References(x => x.Site, "SiteID").LazyLoad();
        References(x => x.Category, "CategoryID").Cascade.SaveUpdate().LazyLoad();

        HasManyToMany<Form>(x => x.PatientInformation)
            .Schema("FormsLibrary")
            .Table("PatientInformationToForms")
            .ParentKeyColumn("FormID")
            .ChildKeyColumn("PatientInformationID")
            .LazyLoad()
            .Cascade.SaveUpdate();
    }
}

************* Domain

 public class PatientInformation : EntityBase<int>
 {
    public PatientInformation()
    {
        this.Forms = new List<Form>();
    }

    public virtual IList<Form> Forms { get; set; }
    public virtual string FullName { get; set; }
    public virtual string DateOfBirth { get; set; }
    public virtual string ContactAccount { get; set; }
 }

public class Form : OrderedEntityBase<int>
{
    public Form()
    {
        this.Active = true;
        this.LastModified = DateTime.Now;
        this.CreatedDate = DateTime.Now;
        this.PatientInformation = new List<PatientInformation>();
    }
    public Form(Site site)
    {
        this.Site = site;
        this.Active = true;
        this.LastModified = DateTime.Now;
        this.CreatedDate = DateTime.Now;
        this.PatientInformation = new List<PatientInformation>();
    }
    public Form(Site site, aspnet_User user)
    {
        this.User = user;
        this.Site = site;
        this.Active = true;
        this.LastModified = DateTime.Now;
        this.CreatedDate = DateTime.Now;
        this.PatientInformation = new List<PatientInformation>();
    }

    public virtual void AddCategory(Category category)
    {
        this.Category = category;
        category.Forms.Add(this);
    }
    public virtual Category Category { get; set; }
    public virtual string Title { get; set; }
    public virtual string Description { get; set; }
    public virtual string FileName { get; set; }
    public virtual string DisplayFileName { get; set; }
    public virtual Site Site { get; protected set; }
    public virtual bool MembersOnly { get; set; }
    public virtual string Status { get; set; }
    public virtual bool Active { get; set; }
    public virtual aspnet_User User { get; set; }
    public virtual DateTime LastModified { get; set; }
    public virtual DateTime CreatedDate { get; protected set; }
    public virtual IList<PatientInformation> PatientInformation { get; set; }

    // do not map
    public virtual void AddPatientInformation(PatientInformation patientInformation)
    {
        if (this.HasPatientInformation(patientInformation))
        {
            this.RemovePatientInformation(patientInformation);
        }
        patientInformation.Forms.Add(this);
        this.PatientInformation.Add(patientInformation);
    }
    public virtual void RemovePatientInformation(PatientInformation patientInformation)
    {
        patientInformation.Forms.Remove(this);
        this.PatientInformation.Remove(patientInformation);
    }
    public virtual bool HasPatientInformation(PatientInformation patientInformation)
    {
        return this.PatientInformation.Contains(patientInformation);
    }
    public virtual void ClearPatientInformation()
    {
        var deletePatientInformation = new List<PatientInformation>();
        foreach (var patientInformation in this.PatientInformation)
        {
            deletePatientInformation.Add(patientInformation);
        }
        foreach (var patientInformation in deletePatientInformation)
        {
            this.RemovePatientInformation(patientInformation);
        }
    }
}

This is where I am adding data to PatientInformation, which includes some commented out code because it wasn't working, but it shows what I have tried.

PatientInformation patientInfo = new PatientInformation();

StatusPlaceHolder.Visible = true;
form.Status = StatusRadioButtonList.SelectedValue != null ? StatusRadioButtonList.SelectedValue : null;

PatientPlaceHolder.Visible = true;
patientInfo.FullName = PatientNameTextBox.Text != null ? PatientNameTextBox.Text : null;
patientInfo.DateOfBirth = DateOfBirthTextBox.Text != null ? DateOfBirthTextBox.Text : null;
patientInfo.ContactAccount = ContactAccountTextBox.Text != null ? ContactAccountTextBox.Text : null;
// need to get form ID to associate this patientinfoID to the formID in PatientInformationToForms table
//form.PatientInformation.Add(patientInfo);
//patientInfo.Form.Add(form);
form.AddPatientInformation(patientInfo);

EDITS I changed the IList name so as not to confuse with the class PatientInformation

 public virtual IList<PatientInformation> PatientInformationList { get; set; }
HasManyToMany<Form>(x => x.PatientInformationList)
            .Schema("FormsLibrary")
            .Table("PatientInformationToForms")
            .ParentKeyColumn("FormID")
            .ChildKeyColumn("PatientInformationID")
            .LazyLoad()
            .Cascade.SaveUpdate();

EDIT

I added .Inverse below and got this error:

The relationship PatientInformation.Forms to PatientInformation.Forms has Inverse specified on both sides. Remove Inverse from one side of the relationship.

 HasManyToMany<PatientInformation>(x => x.Forms)
            .Schema("FormsLibrary")
            .Table("PatientInformationToForms")
            .ParentKeyColumn("PatientInformationID")
            .ChildKeyColumn("FormID")
            .LazyLoad()
            .Inverse()
            .Cascade.SaveUpdate();
Jamie
  • 1,579
  • 8
  • 34
  • 74
  • I'd rename the PatientInformation list to Patientsinformation or PatientInformationList so as not to be confused with the class PatientInformation. I feel like that might be your problem since it could be mixing an object with a list type. – Fran Sep 12 '16 at 16:35
  • Ok I did that, but same error occurs. See above. – Jamie Sep 12 '16 at 16:54
  • I took a look at my own many to many mappings and I'm only mapping one side of the relationship. I then found this http://stackoverflow.com/questions/2722038/many-to-many-mapping-in-nhibernate. Take a look at your mappings. One side of the relationship has to take precendence and the other needs to be marked Inverse(). You mappings have both sides as having precedence. – Fran Sep 12 '16 at 17:10
  • @Fran, I added `.Inverse` to the `PatientInformationList` and new error popped up. `The relationship PatientInformation.Forms to PatientInformation.Forms has Inverse specified on both sides. Remove Inverse from one side of the relationship.` Same thing happens if I try to add `Inverse` to the `Form` mapping. – Jamie Sep 12 '16 at 17:24
  • Look at that error. "PatientInformation.Forms to PatientInformation.Forms" says you still got something wrong with the mapping. if you are marking the relationship inverse, i don't see how you can also be Cascase.SaveUpdate() on it. I'd remove that. – Fran Sep 12 '16 at 17:28
  • the other question is do you need to map both sides of the many to many? How are you accessing this information? is it always patient->patient information -> form? do you ever try to access it the other direction? because if you don't you might just exclude the HasManyToMany from the Form mapping. – Fran Sep 12 '16 at 17:36
  • This information comes from the form. A form gets patient information added to it, and pulled from it. It should be fairly simple, so I don't know why it's giving me a headache. Although, there is an extra table in the database called `PatientInformationToForms` which just stores the `FormID` and the `PatientInformationID` that is associated to that form. – Jamie Sep 12 '16 at 17:39
  • I tried to remove the `HasManyToMany` in the `PatientInformationMap` and it started running, but when I tried to save a form, once again I got the original error about the getter. – Jamie Sep 12 '16 at 17:45

1 Answers1

1

Psychic debugging isn't working for me today. But I think I just saw it. Your HasManyToMany mappings has generic type declaration in the mappings. remove those types. Fluent should be able to infer the type by the lambda expression you give it.

    HasManyToMany<Form>(x => x.PatientInformation)

is in direct conflict. You are saying the many to many is expectings a Form, but you are mapping it to a PatientInformation. remove that type declaration from both sides of your mapping.

public PatientInformationMap()
{
        Schema("FormsLibrary");
        Table("PatientInformation");
        Map(x => x.FullName);
        Map(x => x.DateOfBirth);
        Map(x => x.ContactAccount);

        HasManyToMany(x => x.Forms)
            .Schema("FormsLibrary")
            .Table("PatientInformationToForms")
            .ParentKeyColumn("PatientInformationID")
            .ChildKeyColumn("FormID")
            .LazyLoad()
            .Cascade.SaveUpdate();
    }
}

 public FormMap()
 {
        Schema("FormsLibrary");
        Table("Form");
        Map(x => x.Title);
        Map(x => x.Description);
        Map(x => x.FileName);
        Map(x => x.MembersOnly);
        Map(x => x.Status);
        Map(x => x.Active);
        Map(x => x.DisplayFileName);
        Map(x => x.LastModified);
        Map(x => x.CreatedDate);

        References(x => x.User, "UserID").LazyLoad();
        References(x => x.Site, "SiteID").LazyLoad();
        References(x => x.Category, "CategoryID").Cascade.SaveUpdate().LazyLoad();

        HasManyToMany(x => x.PatientInformation)
            .Schema("FormsLibrary")
            .Table("PatientInformationToForms")
            .ParentKeyColumn("FormID")
            .ChildKeyColumn("PatientInformationID")
            .LazyLoad()
            .Cascade.SaveUpdate();
    }
}

Also check out this series of posts on nhibernate mappings. it is invaluable

http://notherdev.blogspot.com/2012/01/mapping-by-code-onetomany-and-other.html

Fran
  • 6,440
  • 1
  • 23
  • 35