
Image -1- shows ProductsWebAPI for easy scaling in/out with SQL Server
If you have not installed Docker, then please go back to Part I and install Docker for Windows desktop.
OrdersWebApi: Let us do it together (step by step)
Here, I have set the project name to "OrdersSQLite”.



Domain Model and Data Access Layer
- added the entity “Order” to the project.
- added OrdersDBContext to the project and set up the connection string.
- added OrderssController to the project with some logic to handle the requests.
- public class Order
- {
- /// <summary>
- /// Gets or sets the order identifier.
- /// </summary>
- /// <value>The order identifier.</value>
- public int OrderId { get; set; }
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
- /// <summary>
- /// Gets or sets the product Ids.
- /// </summary>
- /// <value>The product Ids.</value>
- Collection<int> ProductIds { get; set; } = new Collection<int>();
- }
- public class OrderDbContext : DbContext
- {
- /// <summary>
- /// Gets or sets the orders.
- /// </summary>
- /// <value>The orders.</value>
- public DbSet<Order> Orders { get; set; }
- /// <summary>
- /// Initializes a new instance of the <see cref="OrderDbContext"/> class.
- /// </summary>
- /// <param name="options">The options.</param>
- public OrderDbContext(DbContextOptions<OrderDbContext> options)
- : base(options)
- {
- }
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- modelBuilder.Entity<Order>().HasData
- (
- new Order { OrderId = 1, Name = "MSDN Order" },
- new Order { OrderId = 2, Name = "Docker Order" },
- new Order { OrderId = 3, Name = "EFCore Order" }
- );
- }
- }
Also, I have added the connection string to the appsettings.json file.
- {
- "Logging": {
- "LogLevel": {
- "Default": "Warning"
- }
- },
- "AllowedHosts": "*",
- "ConnectionStrings": {
- "OrdersConnectionSqlite": "Filename=Orders.db;"
- }
- }
- [ApiController, Route("api/[controller]")]
- public class OrdersController : ControllerBase
- {
- /// <summary>
- /// The orders database context
- /// </summary>
- private readonly OrderDbContext _ordersDbContext;
- /// <summary>
- /// Initializes a new instance of the <see cref="OrdersController"/> class.
- /// </summary>
- /// <param name="ordersDbContext">The orders database context.</param>
- public OrdersController(OrderDbContext ordersDbContext)
- {
- this._ordersDbContext = ordersDbContext;
- }
- //GET: api/Orders
- /// <summary>
- /// Gets the order.
- /// </summary>
- /// <returns>Task<ActionResult<IEnumerable<Order>>>.</returns>
- [HttpGet]
- public async Task<ActionResult<IEnumerable<Order>>> GetOrder()
- {
- return Ok(await _ordersDbContext.Orders.ToListAsync());
- }
- // GET: api/Orders/5
- /// <summary>
- /// Gets the order.
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <returns>Task<ActionResult<Order>>.</returns>
- [HttpGet("{id}")]
- public async Task<ActionResult<Order>> GetOrder(int id)
- {
- var order = await _ordersDbContext.Orders.FindAsync(id);
- if (order == null)
- {
- return NotFound();
- }
- return Ok(order);
- }
- // PUT: api/Orders/5
- /// <summary>
- /// Puts the order.
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <param name="order">The order.</param>
- /// <returns>Task<IActionResult>.</returns>
- [HttpPut("{id}")]
- public async Task<IActionResult> PutOrder(int id, Order order)
- {
- if (id != order.OrderId)
- {
- return BadRequest();
- }
- _ordersDbContext.Entry(order).State = EntityState.Modified;
- try
- {
- await _ordersDbContext.SaveChangesAsync();
- }
- catch (DbUpdateConcurrencyException)
- {
- if (!IsOrderExists(id))
- {
- return NotFound();
- }
- throw;
- }
- return NoContent();
- }
- // POST: api/Orders
- /// <summary>
- /// Posts the order.
- /// </summary>
- /// <param name="order">The order.</param>
- /// <returns>Task<ActionResult<Order>>.</returns>
- [HttpPost]
- public async Task<ActionResult<Order>> PostOrder(Order order)
- {
- _ordersDbContext.Orders.Add(order);
- await _ordersDbContext.SaveChangesAsync();
- return CreatedAtAction("GetOrder", new { id = order.OrderId }, order);
- }
- // DELETE: api/Orders/5
- /// <summary>
- /// Deletes the order.
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <returns>Task<ActionResult<Order>>.</returns>
- [HttpDelete("{id}")]
- public async Task<ActionResult<Order>> DeleteOrder(int id)
- {
- var order = await _ordersDbContext.Orders.FindAsync(id);
- if (order == null)
- {
- return NotFound();
- }
- _ordersDbContext.Orders.Remove(order);
- await _ordersDbContext.SaveChangesAsync();
- return Ok(order);
- }
- /// <summary>
- /// Determines whether [is order exists] [the specified identifier].
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <returns><c>true</c> if [is order exists] [the specified identifier]; otherwise, <c>false</c>.</returns>
- private bool IsOrderExists(int id)
- {
- return _ordersDbContext.Orders.Any(e => e.OrderId == id);
- }
- }
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
- public IConfiguration Configuration { get; }
- // This method gets called by the runtime. Use this method to add services to the container.
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
- services.AddDbContext<OrderDbContext>(options =>
- options.UseSqlite(Configuration.GetConnectionString("OrdersConnectionSqlite")));
- }
- // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
- app.UseMvc();
- }
- }



- public static class ExtensionMethods
- {
- /// <summary>
- /// Migrates the database.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="webHost">The web host.</param>
- /// <returns>IWebHost.</returns>
- public static IWebHost CreateDatabase<T>(this IWebHost webHost) where T : DbContext
- {
- using (var scope = webHost.Services.CreateScope())
- {
- var services = scope.ServiceProvider;
- try
- {
- var db = services.GetRequiredService<T>();
- db.Database.Migrate();
- }
- catch (Exception ex)
- {
- var logger = services.GetRequiredService<ILogger<Program>>();
- logger.LogError(ex, "Database Creation/Migrations failed!");
- }
- }
- return webHost;
- }
- }
- public class Program
- {
- public static void Main(string[] args)
- {
- CreateWebHostBuilder(args).Build().CreateDatabase<OrderDbContext>().Run();
- }
- public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseStartup<Startup>();
- }
- FROM mcr.microsoft.com/dotnet/core/aspnet:2.2-stretch-slim AS base
- WORKDIR /app
- EXPOSE 32034
- FROM mcr.microsoft.com/dotnet/core/sdk:2.2-stretch AS build
- WORKDIR /src
- COPY ["../OrdersSQLite/OrdersSQLite.csproj", "../OrdersSQLite/"]
- RUN dotnet restore "../OrdersSQLite/OrdersSQLite.csproj"
- COPY . .
- WORKDIR "/src/../OrdersSQLite"
- RUN dotnet build "OrdersSQLite.csproj" -c Release -o /app
- FROM build AS publish
- RUN dotnet publish "OrdersSQLite.csproj" -c Release -o /app
- FROM base AS final
- WORKDIR /app
- COPY --from=publish /app .
- ENTRYPOINT ["dotnet", "OrdersSQLite.dll"]
- version: '3.4'
- services:
- OrdersSQLite:
- image: ${DOCKER_REGISTRY}orderswebapi
- build:
- context: .
- dockerfile: ../OrdersSQLite/Dockerfile
- ProductsSqlServer:
- image: ${DOCKER_REGISTRY}productswebapi
- build:
- context: .
- dockerfile: ProductsSqlServer/Dockerfile
- links:
- - sqlserver
- sqlserver:
- image: microsoft/mssql-server-linux:2017-latest
- hostname: 'sqlserver'
- environment:
- ACCEPT_EULA: Y
- SA_PASSWORD: "BigPassw0rd"
- volumes:
- - ./data/mssql:/var/opt/mssql3
- ports:
- - '1433:1433'
- expose:
- - 1433
- - 1433
- version: '3.4'
- services:
- OrdersSQLite:
- environment:
- - ASPNETCORE_ENVIRONMENT=Development
- ports:
- - "32034:80"
- ProductsSqlServer:
- environment:
- - ASPNETCORE_ENVIRONMENT=Development
- ports:
- - "32033:80"

- http://localhost:32034/api/orders
- {"name": "3 Pack Order"}


How can you copy your database locally?
- docker cp f1b9f53be420:/app/orders.db myLocalFilename.db


- EXPLAIN QUERY PLAN SELECT * FROM Orders where OrderId = 2 AND name like '%Docker%'


Summary
You can easily use SQLite and Entity Framework Core in a Docker, but if you want to apply SQLite in the containerized apps, then you have to think about the core Microservices concept (Scalability). How can you scale out (Horizontal Scaling) your services?

Joginder BangerPosted May 6, 2020, 7:34 AM
Hi bro Thanks for userful article. I want the deploy docker image on windows server. can you tell me what is the procedure. thanks joginder