Hello guys, I wonder if I could get some help with a project I'm planning to start. As you all probably know, I'm learning MVC and I've followed dozen of online tutorials, dipped in and out of many books but I got to the conclusion that I have to dive straight in and attempt, hopefully with the help of the community, to build a small, easy application. Obviously, if you think it is too complicated for a beginner, please do let me know.
So, what I've in mind is an application that allows users to enter their own, basic, medical record. I have an HTML version on my local machine, with some sample data. Here are some screenshots of the current version:
screenshot_1.jpg
screenshot_2.jpg

as you can see there are 5 sections:
1)Patient's general info;
2)Blood tests;
3)Jabs and injections;
4)Weight;
5)Exercises;
These last 2 are done with google graph, but I won't use that for the MVC application as it may add another layer of complication.
So, the idea is that users will be able to record all the details listed (all the data wil be saved into a Entity Framework database) and maybe log in before doing so (but I suppose I can always add that to a later date).
Starting with the models, I suppose that each of the 5 sections can be a class, correct? So, for example, let's take the first one, "patient's general info": it'll be something like this:

 public class patientDetails
    {
        public long Id { get; set; }
        public int Height { get; set; }
        public int Age { get; set; }
        public string Allergies{ get; set; }
        public string Operations{ get; set; }
        public string HealthConditions { get; set; }        
    }

and so on for the other sections, although there is a small problem, which is the fact that I have to allow for multiple entries, like, there could be more than one allergy, operation of health conditions, and I'm not entirely sure how to deal with that.
That as far as I got with planning, you're more than welcome to make any suggestions, or highlight things that I might not have thought about that.
Please do let me know what you think about it
Cheers

Mike Askew commented: :o +7

Right, since nobody commented, I decided to start and post very specific questions instead. Also, having had a word with other forum members, there were suggestions that this could, eventually, be made some kind of tutorial to help beginners like me to create a small, (hopefully) working application.
OK. So, I began with creating just my model classes. As I've mentioned in my previous post, I created 5 model classes, one for each "section" I have identified.
-PatienGeneralDetails.cs, containing the general details:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyMedicalRecord_1.Models
{
    public class PatientGeneralDetails
    {
        public int Id { get; set; }
        public int Height { get; set; }
        public int Age { get; set; }
        public List<string> Allergies { get; set; }
        public List<string> Operations { get; set; }
        public List<string> HealthConditions { get; set; }
    }
}

here I used various generic lists here like List<string> Allergies, this should get around the problem of having multiple Allergies, operations and health conditions (thanks to pritaeas for the suggestion).

-PatientBloodTest.cs, containing details of the blood tests taken:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyMedicalRecord_1.Models
{
    public class PatientBloodTest
    {
        public int Id { get; set; }
        public string TestType { get; set; }
        public DateTime DateTaken { get; set; }
    }
}

-PatientJabs.cs, containing details of jabs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyMedicalRecord_1.Models
{
    public class PatientJab
    {
        public int Id { get; set; }
        public string Type { get; set; }
        public List<DateTime> DateDone { get; set; }
    }
}

I used a Generic List here too List<DateTime> DateDone as one jab can be done multple times.

-PatientWeight.cs, containing the weight data. With this users will input their weight on a monthly basis, or as often as they want to:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyMedicalRecord_1.Models
{
    public class PatientWeight
    {
        public DateTime DateChecked { get; set; }
        public double Weight { get; set; }
    }
}

-PatientExercises.cs, containing data on how often users exercise per month. Now, this was a real headache because in my HTML the graph shows pretty well how much you do on a monthly basis, with this instead you will have to input the month manually as well as the frequency, which for me is absolutely fine because this is what I do (I store the gym attendance on my calendar and then at the end of the month I count them up and update the site). I think for the sake of simplicity, this was the best way, but if you can think of a better and easier one, please let me know:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyMedicalRecord_1.Models
{
    public class PatientExercises
    {
        public int Swimming { get; set; }
        public int Walking { get; set; }
        public int Gym { get; set; }
        public string Month { get; set; }
    }
}

So, my questions now:
1)what do you think of my models?
2)Does every model really need an Id? I added it in but I'm not sure it is necessary.
3)The way I envisage this to work, and please let me know if what I'm saying is completely rubbish, is to have a table for each model in the database (I'm using Entity Framework by the way because I don't want to mess around with SQL ).
What do you guys think?

1) With public List<string> Allergies { get; set; } I'd prefer to use a class for an allergy too. Think about it, although a string containing "peanut allergy" might be handy, if you make it a class you can reference the same allergy by ID (in the database, EF connects the objects for you) to different persons without creating duplicates. Also, if you want to add a warning to each allergy, or whatever, you can easily extend the class Allergy without having to change the PatientGeneralDetails.

This can be taken to extremes, but it is good to think about it beforehand. Basically what you are doing is thinking about your ER diagram, without making one. It defines the relations between all your entities.

I am not sure what PatientExcercises is for, but in the same thought you might want a list of PatientExercise so it is more extensible.

2) ID's are useful if at a later point you want to add a relation to something else (foreign key, as described above). You want Allergy to have an ID so you can reference/connect that ID to e.g. a treatment, or a drug.

Thanks pritaeas.
OK so I'll add a Allergy class. Not sure what it needs to contain, but I guess it will be something like

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace MyMedicalRecord_1.Models
{
    public class Allergy
    {
        public int Id { get; set; }
        public string AllergyType { get; set; }        
    }
}

Now, if I have an Allergy class, presumably I can remove this line public List<string> Allergies { get; set; } from the patient class, right?

Basically what you are doing is thinking about your ER diagram, without making one

OK, just a question: do you think that it might help if I in fact draw one? Never done it before, I wouldn't even know how it looks like, but I can look it up and, if it is helpful, I can make one.

I am not sure what PatientExcercises is for...

I don't have to have it, but if you look at the screenshot in the first thread, that's basically the class for the exercises the user does, well, certainly I do :-). I suppose if the user doesn't do any exercise he/she can leave it blank, or not use it.
The exercises are swimming, walking and gym and in my head I thought I'd have a class to represent them: they are ints because users can indicate how many times they have done one or the other: for example, say that in May the user's gone to the gym 6 times, then int Gym will be 6 and Month will be "May". This assumes that users will input the values at the end of the month, rather than when they do the exercises, if it makes any sense. If I turn Exercises into a list can I still get a date to match one or more exercises? Hope it makes sense.

Never done it before, I wouldn't even know how it looks like

Apart from the "official" ER, it is very helpful to use pen and paper to write down your entities and relations between them IMO (one-on-one and one-many for example).

Now, if I have an Allergy class, presumably I can remove this line public List<string> Allergies { get; set; } from the patient class, right?

Well no. You still need a link between the patient and his allergies.

public List<Allergy> Allergies { get; set; }

The point was that you might need more then just a description of the allergy, hence the class.

OK so, I have updated the classes and made some changes:
1)renamed PatientGeneralDetails to Patient;
2)added a new PatientAllergy class as detailed in previous post;
3)each class has an Id as discussed before.
4)draw the class relationships which are the following:
a) Patient and Allergy have a many-to-many relationship (a patient can have 0, 1 or more than 1 allergy and each allergy can be present in many patients);
b)Patient and Jab have a many-to-many relationship (same reasons as above);
c)Patient and BloodTest have a many-to-many relationship (same reasons as above);
d)Patient and Exercises have a many-to-many relationship (same reasons as above);
e)Patient and Weight have a one-to-many relationship because 1 patient can have only 1 weight value but the weight can be the same for different Patients.

Now I understand what you meant when you said that adding classes can be easily be taken to extremes, because the more I look at this class model I have now, the more I think that perhaps we could turn something else into a class: but I suppose what I have is good now, hopefully : - ).

I didn’t want to repeat the classes again so I put them on pastebin, here there are:
http://pastebin.com/AhYbhvkB

Now, providing we’re all happy with the kind of relationships among classes, I wonder: how is Entity Framework going to figure out those relationships? Fair enough we have ID’s but how does EF know that for example, that a Patient can have more than 1 blood test and that each blood test can be done for different patients? I mean, I understand that in the case of allergies as the Patient class has public List<PatientAllergy> PatientAllergies { get; set; } so shouldn’t I include reference to all those classes in my Patient class, so that my Patient class looks like this:

public class Patient
    {
        public int Id { get; set; }
        public int Height { get; set; }
        public int Age { get; set; }
        public List<PatientAllergy> PatientAllergies { get; set; }
        public List<string> Operations { get; set; }
        public List<string> HealthConditions { get; set; }

        public PatientWeight weight { get; set; }
        public List<PatientJab> jab { get; set; }
        public List<PatientBloodTest> test { get; set; }
        public List<PatientExercises> exercise { get; set; }
    }

thanks

how is Entity Framework going to figure out those relationships?

It sees that a Patient contains a List of BloodTest, so it knows that there is a one-to-many relationship between the two. Based on that information the BloodTest table will contain a foreign key to the Patient table, thus linking them.

so that my Patient class looks like this

Yes, that is exactly right.

Cool, thanks. You're saying one-to-many relationship, but I wonder - not sure it is crucial but still - shouldn't it be many-to-many (at least for Patient--Allergy, Patient--Jab, Patient--BloodTest, Patient--Exercise)? I mean each Patient can have more than one Allergy, Jab, BloodTest and Exercise and in turn, each Allergy, Jab, BloodTest and Exercise can "be" in multiple Patients (as in 2 patients can have the same allergy, jab etc).
An exception is the relationship between Patient and Weight, which should be many-to-one (rather than one-to-many as I have initially said) because one Patient can only have one weight but a specific weight can be present in multiple Patients (as in 2 patients may have the same weight).
If the above is not important, then let's forget about it, I was just curious, that's all.
So, now that we have our models, what's the best way to proceed? SHould I first decide how I want the data to be presented to users and then think about the controllers? In the sense that should all the record be displayed in one page or multiple pages or whatever?

I said one to many, because your class contains a date taken. That makes it kinda unique for one specific patient, does it not? If you need it many-to-many in EF, get djjeavons or DaveAmour here, he should know, or what needs changing in that case.

Next step, is subjective I think. Personally, I'd like to have a controller that will at least give me all records, and just one. That way when building/testing the view you can at least see something. Of course you should think about your views, just to know what kind you need, how many, shared views, and so on.

OK cool, no dont' worry I was just curious about the relationship, that's all. I didn't consider the date, so yes you're right it, in that sense it is unique. To be honest, I don't know enough about EF and so on to say that I need a many-to-many relationship, so I'm more than happy with what I have now.
Moving to the controller: I've been thinking about it last night and yes I agree with the idea of having something that allows me to see everything, at least for testing purposes.
The various applications I've done so far, well let's say testing applications really, had only one class or two at most, and I've always created a controller each, whereas here we have mulitple classes related to one another, so I wonder, can I create one single controller (with EF with read/write actions and views) whose views will allow me to have all the form fields (jab, blood tests, weight etc) on the same page, I mean under the same URL rather than having to navigate to different controller for each model? In other words would this one controller, let's call it PatientController take care of everything for me, so I can test whether the data input and returned is OK?

Right, so I created this PatientController, er, but there seems to be something strange happening.
Basically when I created iton the add controller window, I selected the Patient.cs class from the drop down Model Class. Now, the controller has been created successfully as well as the various tables in the database, here is the screenshot:
medical_tables.jpg

And that's always good news. But I then built the application and run it navigating to the Controller URL, and all I get on the page is weight and age:
patientController.jpg
I would have thought I would get all the fields instead, so I checked the automatically generated Create view and strangely enough, there are only weight and age in there. Here is the code generated:

@model MyMedicalRecord_1.Models.Patient

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Patient</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Height)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Height)
            @Html.ValidationMessageFor(model => model.Height)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Age)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Age)
            @Html.ValidationMessageFor(model => model.Age)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Now, I don't believe this is what I'm supposed to see as I should be able to have all the fields available in there, I think?

Actually, having done a bit more digging, I discovered something interesting. The fields displayed are only built-in types, like ints and the missing ones are custom types (I think that's the correct way to identify them), like List<PatientAllergy>, List<string>, PatientWeight. If you look at the below screenshot, you'll see that the custom types are indeed in the database table as you would expect them to be, but, they're just not showing up on the page. Not sure this is a coincidence, is there a special using statement i need to use or something?
patientClass.jpg

Oh no sorry, they are not even in the database...

Am not sure I follow. Do note am not an EF user, and I am not sure what exactly should be generated.

Sorry I posted too many things as I was trying to figure out what was going on, I'll try to explain it more clearly :-).
Basically, I've got all the classes done, they can be seen here http://pastebin.com/AhYbhvkB and then I created my controller as we discussed in one of my latest posts, one controller only so I can test the application and verify that I can add and return data (with read/write action and views using EF). As model class I chose my Patient.css as I cosdider it the "main" class and I created a new data context: then I run the application and a few interesting things happened:
1)if I navigate to the controller URL (http://localhost:62324/Patient/Create) I get this
patient_create.jpg
As you can see there is a lot missing: I only the primitive-type properties are displayed, the non-primitive ones (Operations, Weight etc) are not there instead
and I would have expected to see them there as well, as I would expect to be able to enter weight, blood test, exercises etc...
SO I checked the database, and specifically the Patient table and if you look at the screenshot here patientClass.jpg you'll notice that the patient table has only Age, Weight and Weight_ID (whatever this is) and all the other properties from the class are just missing. What I don't understand is why. I would expect the table to contain all the data in the patient class. I obviously googled it, but I don't seem to be able to find an explanation, and I was wondering if anybody with a bit of EF experience can clarify this for me.
Hope it makes sense now

Please show us the code of all your models.

You should try adding the virtual keyword to relationship definitions.

public virutal List<PatientJab> jabs {get; set;}

And also add the relationship in the other table.

public virtual Patient patient {get; set;}

That defines a one to many relationship between Patient and Jabs.

You should also have models for heathconditions and operations in a one to many relationship with patient.

Also id like you to show us the UML for the database. It would help

Please show us the code of all your models.

See above.

Also id like you to show us the UML for the database.

There is no UML, nor ER.

thanks @pritaeas, I actually came across that link myself, but I'm not terribly sure I understood the whole ting about "virtual", in fact I think I'll take the opportunity to clarify it in this post
@tobyITguy, thanks for your reply. I revised the classes I had before and made some changes, like adding the Operation and HealthCondition classes as you suggeste:d here are the latest changes http://pastebin.com/EcKXWqSK
Now, moving on to the virtual business, let's see if I get this right. If I understand it correctly all non-primitive properties need to be virtual to achieve this "lazy loading" thingy, so, my patient class becomes:

public class Patient
    {
        public int Id { get; set; }
        public int Height { get; set; }
        public int Age { get; set; }
        virtual public List<PatientAllergy> PatientAllergies { get; set; }
        virtual public List<Operation> Operation { get; set; }
        virtual public List<HealthCondition> ConditionName { get; set; }
        virtual public PatientWeight weight { get; set; }
        virtual public List<PatientJab> jab { get; set; }
        virtual public List<PatientBloodTest> test { get; set; }
        virtual public List<PatientExercises> exercise { get; set; }        
    }

I hope I haven't gone too crazy with the virtual keyboards.
The same way, all my other classes, since they are related to the patient one will get this line public virtual Patient patient {get; set;}, so, for example, let's take the PatientAllergy, it now becomes:

public class PatientAllergy
    {
        public int Id { get; set; }
        public string AllergyType { get; set; }
        public virtual Patient patient {get; set;}
    }

and the same for the rest of the classes. Correct?
Cheers

Correct?

Yes, that appears to be correct, based on the link and the reply by tobyITguy.

OK, so I created another application with the new updated classes, it builds OK, but (eh eh yes there is a BUT of course!) there is a problem. It looks like it's not happy about the relationship between the main Patient class and the PatientWeight class: here are both of them:

public class Patient
    {
        public int Id { get; set; }
        public int Height { get; set; }
        public int Age { get; set; }
        virtual public List<PatientAllergy> PatientAllergies { get; set; }
        virtual public List<PatientOperation> Operation { get; set; }
        virtual public List<PatientHealthCondition> ConditionName { get; set; }
        virtual public PatientWeight weight { get; set; }
        virtual public List<PatientJab> jab { get; set; }
        virtual public List<PatientBloodTest> test { get; set; }
        virtual public List<PatientExercises> exercise { get; set; }  
    }

public class PatientWeight
    {
        public int Id { get; set; }
        public DateTime DateChecked { get; set; }
        public double Weight { get; set; }
        public virtual Patient patient { get; set; }
    }

"Unable to retrieve metadata for MyMedicalRecord_2.Models.Patient.
Unable to determine the principal end of an association between the types MyMedicalRecord_2.Models>patientWeight and MyMedicalRecord_2.Models.Patient. The principal end of this association must be explicitly configured using either the relationship fluent API of data annotations"
medical_2.png
I did a bit of googling, and it looks liks it has to do with the type of relationship involved between the two classes. Is it fair to say that the relationship between patient and weight isn't the same as between patient and the other classes (one patient can only have one weight but he can have more than one allergy etc). So, would it be OK to remove public virtual Patient patient { get; set; } from PatientWeight?

So, would it be OK to remove public virtual Patient patient { get; set; } from PatientWeight?

Looks like that would be the problem, so yes I think it would be OK.

You need to annotate and specify the foreign key.

public class PatientWeight
    {   
        [key,ForeignKey("Patient")]
        public int Id { get; set; }
        public DateTime DateChecked { get; set; }
        public double Weight { get; set; }
        public virtual Patient patient { get; set; }
    }

You also need to use this namespace

using System.ComponentModel.DataAnnotations.Schema;

I also noticed your Patient class has no name field.

I think it would be necesary becasue when the relationship is made, you dont wanna be assigning allergies or operations to patients using their ids.

Using names would make it more friendly.

you dont wanna be assigning allergies or operations to patients using their ids.

Care to explain? Makes no sense to me.

Im assuming that theres a view to add allergies which would then require that it be associated with a patient. I.E the person with that allergy.

Check the image of the MVC scaffolded view attached.

Since theres no name property in the patient class. We can't change the view to display names for us to select from rather than IDs.

Hope you understand?

If im getting things wrong, please correct me.

Also if your looking for something like this delete.PNG

Then you can tell me and id give you the classes i used to generate that.

Hope that helps.

Hope you understand?

I do, I misread apparently.

Thanks tobyITguy, yes it makes sense, I should've thought about the name :-). I've got to admit that I'm not entirely clear with all this relationship business - will probably start a thread on that very soon - anyway, I thought that the point of adding public virtual Patient patient { get; set; } to the other classes was to establish a relations among them (like a patient has one weight, multiple allergies etc) and I would've thought that EF had sufficient information to determine what was the primary key and foreign key, evidently I was wrong. So I don't need to remove the virtual class from the PatientWeight - the error isn't complaining that there is a virtual class - but just add the foreign key: now I suppose that the foreign key token (is that called a token) needs to be added to all the other classes as well so that EF can create the relevant relationships in the relational tables

The virtual enables lazy loading(optional- but ive not seen anyone use it without that keyword), the fact that you have Patient Patient along with the key of the class as a property in the related class then your defining a relationship.

OK cool, so the foreign key token [key,ForeignKey("Patient")] needs to be added to every class related to the patient class, correct?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.