In this article, we will create a database with a foreign key constraint (one to many relationship), using Code First technique in an Entity Framework, seed some sample data and return the data, using the Web API.
Before starting, I assume that you have some knowledge of an Entity Framework code first technique, if not you can learn it here.
Entity Framework
Entity Framework is a relational mapper framework. It is an enhancement of ADO.NET, which gives developers an automated mechanism to access and store the data in the database.
Web API
ASP.NET Web API is a framework to build HTTP Service, which reaches a broad range of clients including Browsers and mobile devices.
It is an ideal platform to build RESTtful Services.
Let's start.
Take an empty Web API project and name it.
Click OK and select the empty template with Web API.
This will create an empty project with Web API.
Now, start Package Manager Console.
In Package Manger Console, type Install-Package EntityFramework.
Once an Entity Framework is installed, type Install-Package Newtonsoft.Json and install it as well.
Note
Newtonsoft.JSON is a framework, which is used to serialize or deserialize the objects in JSON format. For more information, click here.
Now, add a connection string in web.config file, as shown below.
- <connectionStrings>
- <add connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=TestDatabase;Integrated Security=True" name="DefaultConnection" providerName="System.Data.SqlClient" />
- </connectionStrings>
Note
When an Application will run for first time, you can see the database in SQL Server Object Explorer under MSSQLLocalDB>Database>TestDatabase.
Now, add a class file in Models folder.
Name it as entites.cs.
Now, replace the code of Entites.cs class with the code given below.
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
-
- namespace Test.Models
- {
- public class Country
- {
- [Key]
- public int CountryId { get; set; }
- public string Name { get; set; }
- public List<State> State { get; set; }
- }
-
- public class State
- {
- [Key]
- public int StateId { get; set; }
- public string Name { get; set; }
- public List<City> City { get; set; }
-
- public int CountryId { get; set; }
- public Country Country { get; set; }
- }
-
- public class City
- {
- [Key]
- public int CityId { get; set; }
- public string Name { get; set; }
-
- public int StateId { get; set; }
- public State State { get; set; }
- }
- }
Note
[Key] defines the Primary key and Table
public int StateId { get; set; } Defines the Foreign Key
public State State { get; set; } Show the relation.
Now, add a folder in root directory and name it as Context.
Now, add DatabaseContext.cs class. In context folder, replace the code with the code given below.
- using System.Data.Entity;
- using Test.Models;
-
- namespace Test.Context
- {
- public class DatabaseContext : DbContext
- {
- public DatabaseContext() : base("DefaultConnection") { }
-
- public DbSet<Country> Countries { get; set; }
- public DbSet<State> States { get; set; }
- public DbSet<City> Cities { get; set; }
- }
- }
DatabaseContext extends DbContext class. This is the main class, which implements all Entity Framework functionality. For more information about DbContext, read this.
Each DbSet<T> represents a table in the database.
Now, add a class in Context folder and name it as DatabaseInitializer.cs.
Now, replace the code of DatabaseInitializer.cs clsass with the code given below.
- using System;
- using System.Collections.Generic;
- using System.Data.Entity;
- using System.Linq;
- using System.Web;
- using Test.Models;
-
- namespace Test.Context
- {
- public class DatabaseInitializer : DropCreateDatabaseIfModelChanges<DatabaseContext>
- {
- protected override void Seed(DatabaseContext context)
- {
- base.Seed(context);
-
- var cityInMaharashtra = new List<City> {
- new City {Name="Mumbai" },
- new City {Name= "Pune" }
- };
- var cityInUttarPradesh = new List<City> {
- new City {Name="Lucknow" },
- new City {Name="Banaras" }
- };
- var cityInTamilnadu = new List<City> {
- new City {Name="Bangaluru" },
- new City {Name="Chennai" }
- };
- var cityInUttaranchal = new List<City> {
- new City {Name="Dehradun" },
- new City {Name="Rishikesh" }
- };
- var cityInPanjab = new List<City> {
- new City {Name="Chandigarh" },
- new City {Name="Ludhiana" }
- };
- var stateInIndia = new List<State> {
- new State {
- Name="Maharashtra",City=cityInMaharashtra
- },
- new State {
- Name="Uttar Pradesh",City=cityInUttarPradesh
- },
- new State {
- Name="Tamil nadu",City=cityInTamilnadu
- },
- new State {
- Name="Uttaranchal",City=cityInUttaranchal
- },
- new State {
- Name="Panjab",City=cityInPanjab
- }
- };
- Country country = new Country
- {
- Name = "India",
- State = stateInIndia
- };
- context.Countries.Add(country);
- context.SaveChanges();
- }
- }
- }
This file has some sample data inside the seed Method. When the application runs for the first time, Code First Migration will create tables specified in DatabaseContext class and the data from seed method will be inserted.
DatabaseInitializer.cs will be called in Application_Start() function in global.asax file, as shown below.
- using System.Web.Http;
- using Test.Context;
-
- namespace Test
- {
- public class WebApiApplication : System.Web.HttpApplication
- {
- protected void Application_Start()
- {
- GlobalConfiguration.Configure(WebApiConfig.Register);
- System.Data.Entity.Database.SetInitializer(new DatabaseInitializer());
- }
- }
- }
Now, our database design has been done.
Let' create our API to return data in JSON format.
Add a Web API Controller inside controller folder.
Name it as DefaultController.
Now, replace the DefaultController.cs class code with the code given below.
- using System;
- using System.Linq;
- using System.Web.Http;
- using Test.Context;
-
- namespace Test.Controllers
- {
- public class DefaultController : ApiController
- {
-
- private DatabaseContext db = new DatabaseContext();
-
-
- [HttpGet]
- public IHttpActionResult Get()
- {
- try
- {
-
- var result = from country in db.Countries
- select new {
- country.CountryId,
- country.Name,
- State = from state in db.States
- where state.CountryId==country.CountryId
- select new {
- state.StateId,
- state.Name,
- City=from city in db.Cities
- where city.StateId==state.StateId
- select new {
- city.CityId,
- city.Name
- }
- }
- };
- return Ok(result);
- }
- catch (Exception)
- {
-
- return InternalServerError();
- }
- }
- }
- }
The code given above has a Get method, which will be invoked when the user will request the URL given below.
Localhost:3000/api/Default
Note:
- Port number 3000 is randomly assigned by Visual Studio, so it will be different on your machine.
- It uses LINQ to an Entity to select the data.
Now, our API is ready but before running, let's change the default behavior of our Application for returning XML data to JSON data in WebApiConfig.cs located under App_Start folder
- using Newtonsoft.Json.Serialization;
- using System.Web.Http;
-
- namespace Test
- {
- public static class WebApiConfig
- {
- public static void Register(HttpConfiguration config)
- {
-
-
-
- config.MapHttpAttributeRoutes();
-
- config.Routes.MapHttpRoute(
- name: "DefaultApi",
- routeTemplate: "api/{controller}/{id}",
- defaults: new { id = RouteParameter.Optional }
- );
-
-
-
- config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
-
-
- config.Formatters.JsonFormatter.SerializerSettings.Formatting =
- Newtonsoft.Json.Formatting.Indented;
-
-
- config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
- new CamelCasePropertyNamesContractResolver();
- }
- }
- }
Now, our API is ready. Let's run.
The above error happens because we haven't specified the URL, so add the /api/Default in your browser URL as highlighted
Now, our API will return the JSON formatted data with one to many relation.
Every country has some sample states, which have their respective cities.