2
votes

I am trying to learn asp.net MVC, by converting a web forms app I have. It's a room booking app, where there is a customer table (tblCustomerBooking) which has a one to many relationship with tblRental - so one customer can book more than one room. The fields that match each other are tblCustomerBooking.customer_id -> tblRental.customer_ref

I'm trying to use code first - and building a model class - but I can't figure out how to link the two tables, so that when I query the dbContext, it will return a customer, with one or more rentals within the same model.

My table definitions are:

CREATE TABLE [dbo].[tblCustomerBooking](
    [customer_id] [bigint] IDENTITY(1,1) NOT NULL,
    [room_id] [bigint] NULL,
    [customer_name] [varchar](110) NULL,
    [customer_email] [varchar](50) NULL
     CONSTRAINT [PK_tblCustomerBooking] PRIMARY KEY CLUSTERED 
(
    [customer_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

CREATE TABLE [dbo].[tblRental](
    [rental_id] [bigint] IDENTITY(1,1) NOT NULL,
    [room_id] [bigint] NOT NULL,
    [check_in] [datetime] NOT NULL,
    [check_out] [datetime] NOT NULL,
    [customer_ref] [bigint] NULL,
    [room_cost] [decimal](18, 2) NULL
 CONSTRAINT [PK_tblRental_1] PRIMARY KEY CLUSTERED 
([rental_id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS      =     ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

My attempt at building the model for this is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.ModelConfiguration.Conventions; 
using System.Data.Entity;

namespace MvcApplication23.Models
{
    public class tblRental 
        {
        [Key()]
        public int rental_id { get; set; }
        public int room_id { get; set; } 
            public DateTime check_in { get; set; } 
            public DateTime check_out { get; set; }
            public long customer_ref { get; set; } 
            [ForeignKey("customer_ref")] 
            public tblCustomerBooking Customer {get;set;} 
            public decimal room_cost { get; set; } 
        } 

    public class tblCustomerBooking 
    {
        [Key()]
        public long customer_id { get; set; } 
        public string customer_name { get; set; } 
        public string customer_email { get; set; } 
        public ICollection<tblRental> Rentals {get;set;} 
    }

    public class RentalContext : DbContext
    {
        public DbSet<tblCustomerBooking> customers { get; set; }
        public DbSet<tblRental> rentals { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        } 
    }
}

Controller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http;
using MvcApplication23.Models;

namespace MvcApplication23.api.Controllers
{
    public class RentalController : ApiController
    {
        private RentalContext db = new RentalContext();

        // GET /api/rental/5
        public IQueryable<tblCustomerBooking> Get(int id)
        {
            return db.customers.Include("rentals").FirstOrDefault(c=>c.customer_id==id);
        }

** I've updated the info above, with the actual table names that already existed in the database **

How to I link the two tables in the model? And then given a customer_id, how would I query the DbContext to return a customer, with any related entries in the tblRental table?

Thank you very much for any pointers,

Mark

2

2 Answers

5
votes

To link two entities, provide a navigation property:

public class Rental
{
    [Key]
    public int rental_id { get; set; }
    public int room_id { get; set; }
    public DateTime check_in { get; set; }
    public DateTime check_out { get; set; }
    public int customer_ref { get; set; }

    [ForeignKey("customer_ref")]
    public virtual Customer Customer {get;set;}

    public decimal room_cost { get; set; }
 }

public class Customer
{
    [Key]
    public int customer_id { get; set; }
    public string customer_name { get; set; }
    public string customer_email { get; set; }

    public virtual ICollection<Rental> Rentals {get;set;}
}

And to query your customer :

return this.DataContext.customers.Include("Rentals").FirstOrDefaul(c=>c.customer_id==customerId);
0
votes
using System.ComponentModel.DataAnnotations.Schema;


public class Rental
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual int id { get; set; }
    public virtual int room_id { get; set; }
    public virtual DateTime check_in { get; set; }
    public virtual DateTime check_out { get; set; }
    public virtual int customer_id { get; set; }
    public virtual decimal room_cost { get; set; }

    #region Navigation Properties
    [ForeignKey("customer_id")]
    public virtual Customer Customer {  get;  set;  }
    #endregion
}

public class Customer
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int id { get; set; }
    public string name { get; set; }
    public string email { get; set; }

    public virtual ICollection<Rental> Rentals {get;set;}
}