简体   繁体   中英

C# Entity Framework - correct setup of models and read related data

I have the following models for a hospital system I am trying to create. I have the models setup as shown:

public class Patient
{
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]

    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public DateTime DOB { get; set; }

    public string FullName
    {
        get { return FirstName + ' ' + LastName; }
    }

    public virtual ICollection<InPatient> InPatients { get; set; }
}

public class InPatient
{
    public int ID { get; set; }
    public int Spell { get; set; }
    public int PatientID { get; set; }
    public int BedID { get; set; }
    public int SourceID { get; set; }
    public DateTime SourceDT { get; set; }
    public string Destination { get; set; }
    public DateTime? DestinationDT { get; set; }
    public int Action { get; set; }

    virtual public Patient Patient { get; set; }
    virtual public Bed Bed { get; set; }
}

public class Bed
{
    public int ID { get; set; }
    public int WardID { get; set; }
    public string BedTitle { get; set; }
    public string BedSex { get; set; }
    public string BedType { get; set; }

    public virtual ICollection<InPatient> Inpatients { get; set; }
    public virtual Ward Ward { get; set; }
}

public class Ward
{
    public int ID { get; set; }
    public string WardTitle { get; set; }

    public virtual ICollection<Bed> Beds { get; set; }
}

I have also created a WardIndexData.

public class WardIndexData
{
    public IEnumerable<InPatient> InPatients { get; set; }
    public IEnumerable<Patient> Patients { get; set; }
    public IEnumerable<Bed> Beds { get; set; }
    public IEnumerable<Ward> Wards { get; set; }
}

For the controller, I am trying to have the Ward accessed via ward/details/WardID . From this, depending on the ID, it will then show all the beds for that ward (occupied or not), and the patients in the bed depending on the InPatient table - BedID matching up and there is no DestinationDT (therefore the patient is still there).

For my controller class, I really have no idea how to get the ward to return the patient. I have had success getting the list of beds, but that is it, and I have since lost that playing about with the code. I know as it currently stands it is a complete mess, but that's because I'm completely confused and hashing things together to get something to work. I'm literally pulling my hair out trying to figure this out.

    public ActionResult Details(int? id)
    { 
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }

        var viewModel = new WardIndexData();

        viewModel.InPatients = db.InPatients
            .Where(i => i.BedID == b.BedID)
            .Include(i => i.SourceDT)
            .Include(i => i.Bed.BedTitle)
            .Include(i => i.Patient.FullName)
            .Include(i => i.Bed.Ward.WardTitle);

        return View(viewModel);
    }

And the View (which I also know spits out errors):

@model APT.ViewModels.WardIndexData

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<div>
    <h4>Ward</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.WardTitle)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.WardTitle)
        </dd>

    </dl>
    <table class="ward">
        <tr>
            <th>Bed #</th>
            <th>Patient Name</th>
            <th>Admitted Date</th>
        </tr>
        @foreach(var item in Model.Beds)
        {
            ViewBag.bID = item.ID;
            <tr>
                <td>
                    @Html.DisplayFor(ModelItem => item.BedTitle)
                </td>
                <td>
                    Patient Name
                </td>
                <td>
                    Admitted Date
                </td>
            </tr>
        }
    </table>

</div>
<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.ID }) |
    @Html.ActionLink("Back to List", "Index")
</p>

Could someone please show me what I'm doing wrong

Not everything is clear, but making some assumptions I will try to help.

I understand you want to display a Ward with list of beds and patients in beds (Inpatients). First of all, I can see your Bed type has a collection of InPatient objects. So I believe you need to display patients in beds in some point in time. My assumption is you want to display it for a DateTime.Now , and the patient uses the bed between SourceDT and DestinationDT .

For of all, your view model should reflect what you want to display on the view, so the WardViewModel (called by you WardIndexData ) should look more like this:

public class WardViewModel
{
    public string Name { get; set; }
    public IList<BedInWardViewModel> Beds { get; set; }
}

and BedInWardViewModel :

public class BedInWardViewModel
{
    public string Title { get; set; }
    public string PatientName { get; set; }
    public string Admitted { get; set; }
}

So, you should write your LINQ query to get only these values you really need to show in your view, not half of the database, as your application would kill the database very soon.

So the query should be like this (not tested):

var viewModel = 
    db.Wards
        .Where(w => w.ID == id)
        .Select(w => new WardViewModel
            {
                Name = w.WardTitle,
                Beds = w.Beds
                    .Select(b => new
                        {
                            b.BedTitle,
                            InPatient = b.Inpatients.FirstOrDefault(
                                i => i.SourceDT < DateTime.Now && (!i.DestinationDT.HasValue || i.DestinationDT > DateTime.Now))
                        })
                    .Select(x => new BedInWardViewModel
                        {
                            Name = x.BedTitle,
                            PatientName = x.InPatient == null ? "[Free]" : x.Patient.Patient.FirstName + " " + x.InPatient.Patient.LastName,
                            Admitted = x.InPatient == null ? "[NA]" : x.InPatient.SourceDT.ToString()
                        })
                    .ToList()
            })
        .Single();

"Double" select inside the main query is needed to make sure you are not trying to access patient data on empty beds.

The view should be changed to reflect changes in view model, but I believe it should be straight forward.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM