persistence, mediator

This commit is contained in:
Michele 2020-11-06 23:53:37 +00:00
parent 2372fbb620
commit e96a3ef09f
15 changed files with 284 additions and 34 deletions

15
.vscode/launch.json vendored
View file

@ -2,7 +2,7 @@
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"version": "0.2.0",
"configurations": [
{
"name": "Docker .NET Core Attach (Preview)",
@ -18,7 +18,18 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build sledgemapper",
"program": "${workspaceFolder}/Sledgemapper/bin/Debug/netcoreapp3.1/sledgemapper.dll",
"program": "${workspaceFolder}/Sledgemapper/bin/Debug/net5.0/sledgemapper.dll",
"args": [],
"cwd": "${workspaceFolder}/Sledgemapper",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Sledgemapper.API",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build sledgemapper.api",
"program": "${workspaceFolder}/Sledgemapper.Api/bin/Debug/net5.0/sledgemapper.api.dll",
"args": [],
"cwd": "${workspaceFolder}/Sledgemapper",
"console": "internalConsole",

34
Sledgemapper.Api/.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,34 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/net5.0/Sledgemapper.Api.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}

42
Sledgemapper.Api/.vscode/tasks.json vendored Normal file
View file

@ -0,0 +1,42 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Sledgemapper.Api.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Sledgemapper.Api.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/Sledgemapper.Api.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
}

View file

@ -0,0 +1,51 @@
using System;
using System.Security.AccessControl;
using Microsoft.EntityFrameworkCore;
using Sledgemapper.Api.Models;
using System.Reflection;
namespace Sledgemapper.Api.Data
{
public static class DbInitializer
{
public static void Initialize(MyDbContext context)
{
context.Database.EnsureCreated();
}
}
public class MyDbContext : DbContext
{
public DbSet<MapLog> MapLogs { get; set; }
public MyDbContext(DbContextOptions options):base(options)
{}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// optionsBuilder.
// options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName);
// optionsBuilder.UseSqlite("Filename=SledgemapperDatabase.db", options =>
// {
// options.MigrationsAssembly(Assembly.GetExecutingAssembly().FullName);
// });
optionsBuilder.UseSqlite("Filename=MyDatabase.db");
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Map table names
modelBuilder.Entity<MapLog>().ToTable("MapLog", "dbo");
modelBuilder.Entity<MapLog>(entity =>
{
entity.HasKey(e => e.MapLogId);
//entity.HasIndex(e => {e.SessionName, e.Timestamp});
});
base.OnModelCreating(modelBuilder);
}
}
}

View file

@ -1,3 +1,4 @@
using System.Security.AccessControl;
using Microsoft.AspNetCore.SignalR;
using System.Collections.Generic;
using System.Linq;
@ -6,14 +7,19 @@ using System.Collections.Concurrent;
using Sledgemapper.Shared.Entities;
using Sledgemapper.Clients;
using MediatR;
using System;
using Sledgemapper.Api.Data;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace SignalRChat.Hubs
{
public class SledgemapperHub : Hub<ISledgemapperClient>
{
private readonly IMediator _mediator;
private readonly IMediator _mediator;
private readonly MyDbContext _dbcontext;
public SledgemapperHub(IMediator mediator) => _mediator = mediator;
// public SledgemapperHub(IMediator mediator) => _mediator = mediator;
public SledgemapperHub(MyDbContext dbcontext, IMediator _mediator) =>{ _dbcontext = dbcontext; _mediator=mediator};
private static Dictionary<string, SessionData> _sessions = new Dictionary<string, SessionData>();
public List<string> Colors = new List<string>{"CC0000",
"CC3300",
@ -27,12 +33,23 @@ private readonly IMediator _mediator;
public async Task NewTile(string sessionName, Tile tile)
{
var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
var existingTile = _sessions[sessionName].Map.TryGetValue(tile.ToString(), out var t);
if (existingTile)
{
_sessions[sessionName].Map.TryRemove(t.ToString(), out var rtile);
}
_sessions[sessionName].Map.TryAdd(tile.ToString(), tile);
var jsonString = JsonSerializer.Serialize<Tile>(tile);
_dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog{
Operation="N", SessionName=sessionName, Type="T", Timestamp=timestamp, Object=jsonString
});
await _dbcontext.SaveChangesAsync();
await Clients.Group(sessionName).NewTile(tile);
}
@ -49,12 +66,19 @@ private readonly IMediator _mediator;
public async Task NewOverlay(string sessionName, Overlay tile)
{
var timestamp = DateTimeOffset.Now.ToUnixTimeMilliseconds();
var existingTile = _sessions[sessionName].Overlays.TryGetValue(tile.ToString(), out var t);
if (existingTile)
{
_sessions[sessionName].Overlays.TryRemove(t.ToString(), out var rtile);
}
_sessions[sessionName].Overlays.TryAdd(tile.ToString(), tile);
var jsonString = JsonSerializer.Serialize<Overlay>(tile);
_dbcontext.MapLogs.Add(new Sledgemapper.Api.Models.MapLog{
Operation="N", SessionName=sessionName, Type="O", Timestamp=timestamp, Object=jsonString
});
await _dbcontext.SaveChangesAsync();
await Clients.Group(sessionName).NewOverlay(tile);
}
@ -85,6 +109,7 @@ private readonly IMediator _mediator;
session.Players.Add(player);
_sessions.Add(sessionName, session);
await Groups.AddToGroupAsync(Context.ConnectionId, sessionName);
return session;
}
@ -123,8 +148,8 @@ private readonly IMediator _mediator;
_sessions[sessionName].Map = map.Map;
_sessions[sessionName].Overlays = map.Overlays;
_sessions[sessionName].Walls = map.Walls;
await Clients.Group(sessionName).UpdateMap( _sessions[sessionName]);
await Clients.Group(sessionName).UpdateMap(_sessions[sessionName]);
}
}
}

View file

@ -0,0 +1,30 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Api.Models
{
public class MapLog
{
[Key]
public int MapLogId { get; set; }
[Required]
public string SessionName { get; set; }
[Required]
[MaxLength(1)]
public string Operation { get; set; }
[Required]
[MaxLength(256)]
public string Type { get; set; }
[Required]
[MaxLength(256)]
public string Object { get; set; }
[Required]
public double Timestamp { get; set; }
}
}

View file

@ -0,0 +1,18 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace Sledgemapper.Api.Models
{
public class Snapshot
{
[Key]
public int SnapshotId { get; set; }
[Required]
public string Object { get; set; }
[Required]
public double Timestamp { get; set; }
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -4,8 +4,10 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Sledgemapper.Api.Data;
namespace SignalRChat
{
@ -13,7 +15,9 @@ namespace SignalRChat
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
var host = CreateHostBuilder(args).Build();
CreateDbIfNotExists(host);
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
@ -22,5 +26,23 @@ namespace SignalRChat
{
webBuilder.UseStartup<Startup>();
});
private static void CreateDbIfNotExists(IHost host)
{
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<MyDbContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred creating the DB.");
}
}
}
}
}

View file

@ -6,6 +6,12 @@
<ItemGroup>
<PackageReference Include="mediatr" Version="9.0.0" />
<PackageReference Include="mediatr.extensions.microsoft.dependencyinjection" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.9">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.9" />
</ItemGroup>
<PropertyGroup>

View file

@ -10,6 +10,9 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SignalRChat.Hubs;
using MediatR.Pipeline;
using Sledgemapper.Api.Data;
using Microsoft.EntityFrameworkCore;
namespace SignalRChat
{
public class Startup
@ -17,6 +20,7 @@ namespace SignalRChat
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
@ -27,6 +31,10 @@ namespace SignalRChat
services.AddRazorPages();
services.AddSignalR();
// services.AddMediatR(typeof(Startup));
services.AddDbContext<MyDbContext>(options => options.UseSqlite("Data Source=sledgemapper.db"));
// services.AddEntityFrameworkSqlite().AddDbContext<MyDbContext>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

Binary file not shown.

View file

@ -13,7 +13,7 @@ using System.IO;
using System.Linq;
using System;
using System.Collections.Concurrent;
using Sledgemapper.Entities;
using Sledgemapper.Shared.Entities;
namespace Sledgemapper
{
@ -58,13 +58,12 @@ namespace Sledgemapper
Window.AllowUserResizing = true;
Players = new List<Player>();
connection = new HubConnectionBuilder()
.WithAutomaticReconnect()
#if DEBUG
.WithUrl("http://localhost:5000/ChatHub")
#else
.WithUrl("http://hub.michelescandura.com:5000/ChatHub")
#endif
.Build();
// .WithAutomaticReconnect()
.WithUrl("http://localhost:5000/SledgemapperHub")
// .WithUrl("http://hub.michelescandura.com:5000/SledgemapperHub")
.Build();
connection.On<SessionData>("UpdateMap", (map) =>
{
@ -262,7 +261,11 @@ namespace Sledgemapper
}
successful = session != null;
}
catch { }
catch (Exception ex)
{
}
if (successful)
{
_session = textbox.Text;
@ -276,8 +279,8 @@ namespace Sledgemapper
window.Closed += (s, a) =>
{
// Called when window is closed
};
// Called when window is closed
};
window.ShowModal(_desktop);
};
@ -297,8 +300,8 @@ namespace Sledgemapper
RowSpacing = 3,
};
// Set partitioning configuration
grid.ColumnsProportions.Add(new Proportion(ProportionType.Auto));
// Set partitioning configuration
grid.ColumnsProportions.Add(new Proportion(ProportionType.Auto));
grid.ColumnsProportions.Add(new Proportion(ProportionType.Fill));
grid.RowsProportions.Add(new Proportion(ProportionType.Auto));
grid.RowsProportions.Add(new Proportion(ProportionType.Auto));
@ -318,15 +321,15 @@ namespace Sledgemapper
content.Widgets.Add(grid);
// var content = new VerticalStackPanel();
// var textbox = new TextBox();
// TextButton button = new TextButton
// {
// Text = "Start",
// HorizontalAlignment = HorizontalAlignment.Center
// };
button.Click += async (s, e) =>
{
// var content = new VerticalStackPanel();
// var textbox = new TextBox();
// TextButton button = new TextButton
// {
// Text = "Start",
// HorizontalAlignment = HorizontalAlignment.Center
// };
button.Click += async (s, e) =>
{
if (string.IsNullOrWhiteSpace(textbox.Text))
{
return;
@ -353,14 +356,14 @@ namespace Sledgemapper
window.Close();
}
};
//content.Widgets.Add(textbox);
content.Widgets.Add(button);
//content.Widgets.Add(textbox);
content.Widgets.Add(button);
window.Content = content;
window.Closed += (s, a) =>
{
// Called when window is closed
};
// Called when window is closed
};
window.ShowModal(_desktop);
};