Skip to content

Commit

Permalink
Updated data chapter with EF, caching, NoSQL
Browse files Browse the repository at this point in the history
Added caching support and some diagnostic code.
  • Loading branch information
ardalis committed Apr 23, 2017
1 parent a69afa2 commit 708e852
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 10 deletions.
Binary file not shown.
4 changes: 3 additions & 1 deletion src/ApplicationCore/Entities/CatalogBrand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace Microsoft.eShopWeb.ApplicationCore.Entities
using System.Collections.Generic;

namespace Microsoft.eShopWeb.ApplicationCore.Entities
{
public class CatalogBrand : BaseEntity<int>
{
Expand Down
1 change: 1 addition & 0 deletions src/Web/Infrastructure/CatalogContext.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.eShopWeb.ApplicationCore.Entities;

namespace Microsoft.eShopWeb.Infrastructure
{

Expand Down
54 changes: 54 additions & 0 deletions src/Web/Services/CachedCatalogService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.eShopWeb.ViewModels;
using Microsoft.Extensions.Caching.Memory;
using System;

namespace Microsoft.eShopWeb.Services
{
public class CachedCatalogService : ICatalogService
{
private readonly IMemoryCache _cache;
private readonly CatalogService _catalogService;
private static readonly string _brandsKey = "brands";
private static readonly string _typesKey = "types";
private static readonly string _itemsKeyTemplate = "items-{0}-{1}-{2}-{3}";
private static readonly TimeSpan _defaultCacheDuration = TimeSpan.FromSeconds(30);

public CachedCatalogService(IMemoryCache cache,
CatalogService catalogService)
{
_cache = cache;
_catalogService = catalogService;
}

public async Task<IEnumerable<SelectListItem>> GetBrands()
{
return await _cache.GetOrCreateAsync(_brandsKey, async entry =>
{
entry.SlidingExpiration = _defaultCacheDuration;
return await _catalogService.GetBrands();
});
}

public async Task<Catalog> GetCatalogItems(int pageIndex, int itemsPage, int? brandID, int? typeId)
{
string cacheKey = String.Format(_itemsKeyTemplate, pageIndex, itemsPage, brandID, typeId);
return await _cache.GetOrCreateAsync(cacheKey, async entry =>
{
entry.SlidingExpiration = _defaultCacheDuration;
return await _catalogService.GetCatalogItems(pageIndex, itemsPage, brandID, typeId);
});
}

public async Task<IEnumerable<SelectListItem>> GetTypes()
{
return await _cache.GetOrCreateAsync(_typesKey, async entry =>
{
entry.SlidingExpiration = _defaultCacheDuration;
return await _catalogService.GetTypes();
});
}
}
}
46 changes: 44 additions & 2 deletions src/Web/Services/CatalogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,30 @@
using Microsoft.eShopWeb.Infrastructure;
using Microsoft.eShopWeb.ViewModels;
using Microsoft.eShopWeb.ApplicationCore.Entities;
using System.Data.SqlClient;
using Dapper;
using Microsoft.Extensions.Logging;

namespace Microsoft.eShopWeb.Services
{
public class CatalogService : ICatalogService
{
private readonly CatalogContext _context;
private readonly IOptionsSnapshot<CatalogSettings> _settings;
private readonly ILogger<CatalogService> _logger;

public CatalogService(CatalogContext context, IOptionsSnapshot<CatalogSettings> settings)
public CatalogService(CatalogContext context,
IOptionsSnapshot<CatalogSettings> settings,
ILoggerFactory loggerFactory)
{
_context = context;
_settings = settings;
_settings = settings;
_logger = loggerFactory.CreateLogger<CatalogService>();
}

public async Task<Catalog> GetCatalogItems(int pageIndex, int itemsPage, int? brandId, int? typeId)
{
_logger.LogInformation("GetCatalogItems called.");
var root = (IQueryable<CatalogItem>)_context.CatalogItems;

if (typeId.HasValue)
Expand Down Expand Up @@ -50,7 +58,29 @@ public async Task<Catalog> GetCatalogItems(int pageIndex, int itemsPage, int? br

public async Task<IEnumerable<SelectListItem>> GetBrands()
{
_logger.LogInformation("GetBrands called.");
var brands = await _context.CatalogBrands.ToListAsync();

//// create
//var newBrand = new CatalogBrand() { Brand = "Acme" };
//_context.Add(newBrand);
//await _context.SaveChangesAsync();

//// read and update
//var existingBrand = _context.Find<CatalogBrand>(1);
//existingBrand.Brand = "Updated Brand";
//await _context.SaveChangesAsync();

//// delete
//var brandToDelete = _context.Find<CatalogBrand>(2);
//_context.CatalogBrands.Remove(brandToDelete);
//await _context.SaveChangesAsync();

//var brandsWithItems = await _context.CatalogBrands
// .Include(b => b.Items)
// .ToListAsync();


var items = new List<SelectListItem>
{
new SelectListItem() { Value = null, Text = "All", Selected = true }
Expand All @@ -65,6 +95,7 @@ public async Task<IEnumerable<SelectListItem>> GetBrands()

public async Task<IEnumerable<SelectListItem>> GetTypes()
{
_logger.LogInformation("GetTypes called.");
var types = await _context.CatalogTypes.ToListAsync();
var items = new List<SelectListItem>
{
Expand All @@ -88,5 +119,16 @@ private List<CatalogItem> ComposePicUri(List<CatalogItem> items)

return items;
}

//public async Task<IEnumerable<CatalogType>> GetCatalogTypes()
//{
// return await _context.CatalogTypes.ToListAsync();
//}

//private readonly SqlConnection _conn;
//public async Task<IEnumerable<CatalogType>> GetCatalogTypesWithDapper()
//{
// return await _conn.QueryAsync<CatalogType>("SELECT * FROM CatalogType");
//}
}
}
37 changes: 31 additions & 6 deletions src/Web/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
using Microsoft.Extensions.Logging;
using Infrastructure.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using System.Text;
using Microsoft.AspNetCore.Http;

namespace Microsoft.eShopWeb
{
public class Startup
{
private IServiceCollection _services;
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
Expand All @@ -35,8 +38,8 @@ public void ConfigureServices(IServiceCollection services)
{
try
{
c.UseInMemoryDatabase("Catalog");
//c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection"));
//c.UseInMemoryDatabase("Catalog");
c.UseSqlServer(Configuration.GetConnectionString("CatalogConnection"));
c.ConfigureWarnings(wb =>
{
//By default, in this application, we don't want to have client evaluations
Expand All @@ -51,17 +54,20 @@ public void ConfigureServices(IServiceCollection services)

// Add Identity DbContext
services.AddDbContext<AppIdentityDbContext>(options =>
options.UseInMemoryDatabase("Identity"));
// options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));
//options.UseInMemoryDatabase("Identity"));
options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));

services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();


services.AddTransient<ICatalogService, CatalogService>();
services.AddMemoryCache();
services.AddScoped<ICatalogService, CachedCatalogService>();
services.AddScoped<CatalogService>();
services.Configure<CatalogSettings>(Configuration);
services.AddMvc();

_services = services;
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand All @@ -74,6 +80,25 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();

app.Map("/allservices", builder => builder.Run(async context =>
{
var sb = new StringBuilder();
sb.Append("<h1>All Services</h1>");
sb.Append("<table><thead>");
sb.Append("<tr><th>Type</th><th>Lifetime</th><th>Instance</th></tr>");
sb.Append("</thead><tbody>");
foreach (var svc in _services)
{
sb.Append("<tr>");
sb.Append($"<td>{svc.ServiceType.FullName}</td>");
sb.Append($"<td>{svc.Lifetime}</td>");
sb.Append($"<td>{svc.ImplementationType?.FullName}</td>");
sb.Append("</tr>");
}
sb.Append("</tbody></table>");
await context.Response.WriteAsync(sb.ToString());
}));
}
else
{
Expand Down
2 changes: 2 additions & 0 deletions src/Web/Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Dapper" Version="1.50.2" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.0" />
Expand All @@ -20,6 +21,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="1.1.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.0.0-msbuild3-final" />
Expand Down
3 changes: 2 additions & 1 deletion src/Web/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
"Default": "Warning",
"Microsoft" : "Warning"
}
}
}

0 comments on commit 708e852

Please sign in to comment.