# DDD, C#,
### 課程jamboard
* https://jamboard.google.com/d/1tExzdJz67TyKzBTz4h07BJA_C2a-tTwyjGkHPEYIeS8/edit?usp=sharing
### 可以參考的
* https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/common-web-application-architectures
*
### 預先安裝工具
#### dotnet SDK
* https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/sdk-6.0.402-windows-x64-installer
* ### 測試方式, 打開cmd
* `dotnet --version`
#### Visual Studio Code
* https://code.visualstudio.com/
* 順便安裝C# extension
* link:
```
名稱: C#
識別碼: ms-dotnettools.csharp
描述: C# for Visual Studio Code (powered by OmniSharp).
版本: 1.25.0
發行者: Microsoft
VS Marketplace 連結: https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp
```

#### git
* git --version
* https://github.com/git-for-windows/git/releases/download/v2.38.1.windows.1/Git-2.38.1-64-bit.exe
* 順便安裝git extension
* gitgraph:
```
名稱: Git Graph
識別碼: mhutchie.git-graph
描述: View a Git Graph of your repository, and perform Git actions from the graph.
版本: 1.30.0
發行者: mhutchie
VS Marketplace 連結: https://marketplace.visualstudio.com/items?itemName=mhutchie.git-graph
```

#### db-browser
* https://sqlitebrowser.org/dl/
* https://download.sqlitebrowser.org/DB.Browser.for.SQLite-3.12.2-win64.msi

### 額外使用的
#### Figma
* https://www.figma.com/
# 建立目錄用VSCode開
```
\DDD_C#_2022_Oct_21
```
### 安裝的plugin
* Rest Client
```
名稱: REST Client
識別碼: humao.rest-client
描述: REST Client for Visual Studio Code
版本: 0.25.1
發行者: Huachao Mao
VS Marketplace 連結: https://marketplace.visualstudio.com/items?itemName=humao.rest-client
```
* nuget reverse

```
名稱: NuGet Reverse Package Search ("Add Package" support)
識別碼: jesschadwick.nuget-reverse-package-search
描述: Adds reverse .NET package lookup support like the "Add Package" context menu item in full Visual Studio
版本: 0.1.68
發行者: Jess Chadwick
VS Marketplace 連結: https://marketplace.visualstudio.com/items?itemName=jesschadwick.nuget-reverse-package-search
```
## Lab1
* dotnet 能夠有的版型
```
dot net --list
dotnet dev-certs https --trust
```
* https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215
* https://zh.wikipedia.org/zh-tw/%E7%BB%9F%E4%B8%80%E5%BB%BA%E6%A8%A1%E8%AF%AD%E8%A8%80
* https://app.diagrams.net/
# https://zh.wikipedia.org/zh-tw/%E6%B5%8B%E8%AF%95%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91
## lab1
```
dotnet new sln -o lab1_nunit_unit_test
cd lab1_nunit_unit_test
git init
```
* .gitignore
```
bin/
obj/
Migrations/
```
# 注意在lab1*下
```
dotnet new classlib -o PrimeService
dotnet new nunit -o PrimeService.Tests
```
# 複製.gitignore



# 在加入方案前
```
dotnet build
```

# add projects to solution
```
dotnet sln add .\PrimeService\PrimeService.csproj
dotnet build
dotnet sln add .\PrimeService.Tests\PrimeService.Tests.csproj
dotnet build
dotnet test
```
# 加入一個專案

# 加入兩個專案

# 加入後

```
dotnet add PrimeService.Tests\PrimeService.Tests.csproj reference PrimeService\PrimeService.csproj
```
# `ctrl+P` find file quickly
# PrimeService下新增Class1.cs
```csharp
using System;
namespace Prime.Services;
public class PrimeService
{
public bool IsPrime(int c){
if (c == 1) {
return false;
}
throw new NotImplementedException("程式還沒寫");
}
}
```
# https://docs.nunit.org/articles/nunit/writing-tests/attributes/apartment.html
# PrimeService.Test.cs
```csharp
namespace Prime.Services.Tests;
public class PrimeTest1
{
[OneTimeSetUp]
public void init()
{
Console.WriteLine("只啟動一次");
TestContext.Progress.WriteLine("只啟動一次");
}
[OneTimeTearDown]
public void final()
{
Console.WriteLine("一次性的清除");
TestContext.Progress.WriteLine("一次性的清除");
}
[TearDown]
public void cleanUp()
{
Console.WriteLine("儲存資料清理環境");
}
[Test]
public void checkCondition()
{
Console.WriteLine("測試前置作業");
Assert.Pass();
}
[Test]
[Ignore("尚未實作完成")]
public void checkCondition2()
{
Console.WriteLine("檢查資料");
Assert.Fail("意料中的失敗");
}
[SetUp]
public void prepare()
{
Console.WriteLine("測試前的準備");
service = new PrimeService();
}
private PrimeService service = null!;
[Test]
public void test1IsPrime()
{
bool result = service.IsPrime(1);
Assert.False(result, "1應該不是質數");
}
}
```

## ctrl+click點擊

# git graph

# 
# https://drive.google.com/file/d/1kh8vvj8GFuulOQO8pmEt4vWW_Y05WXdk/view?usp=sharing
# 生成lab2的方案
```
dotnet new sln -o lab2_rest_client
cd lab2_rest_client
dotnet new webapi -o lab2_rest_api
git init
```


```
dotnet run --project lab2_rest_api
```

# https://localhost:7175
# https://localhost:7175/WeatherForecast
# https://petstore.swagger.io/?_ga=2.57332200.33774714.1666337891-701740915.1666337891#/pet/uploadFile

## 創建檔名為`GetWeatherForecast.http`
```
@REQUEST_SERVER = https://localhost:7175
GET {{REQUEST_SERVER}}/WeatherForecast
### 可以再測試另一組
GET {{REQUEST_SERVER}}/WeatherForecast
```
# 完成的lab2
* thttps://drive.google.com/file/d/1HCJuTTT8jDjDHtqVGCuoDQuMI40HFSzV/view?usp=sharing
# https://ithelp.ithome.com.tw/articles/10220739
# day2
```
名稱: NuGet Reverse Package Search ("Add Package" support)
識別碼: jesschadwick.nuget-reverse-package-search
描述: Adds reverse .NET package lookup support like the "Add Package" context menu item in full Visual Studio
版本: 0.1.68
發行者: Jess Chadwick
VS Marketplace 連結: https://marketplace.visualstudio.com/items?itemName=jesschadwick.nuget-reverse-package-search
```
```
dotnet new console -o lab3_di_package_search
```
# `DI.cs`
```csharp!
namespace Lab3;
public static class DependencyInjuection {
public static IServiceCollection Sample(this IServiceCollection services){
}
}
```
# ctrl+P ==> 找檔案
# ctrl+shift+P ==> 啟動功能

```
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.0.0" />
```
```
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
</ItemGroup>
```
```
dotnet add . package Microsoft.Extensions.DependencyInjection.Abstractions
```
```xml!
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
</ItemGroup>
</Project>
```
# `ctrl+.`

```csharp!
using Microsoft.Extensions.DependencyInjection;
namespace Lab3;
public static class DependencyInjuection {
public static IServiceCollection Sample(this IServiceCollection services){
return services;
}
}
```
```csharp!
using Microsoft.Extensions.DependencyInjection;
namespace Lab3
{
public static class DI
{
public static IServiceCollection Sample(this IServiceCollection services)
{
return services;
}
}
}
```
# https://drive.google.com/file/d/1-5Eg67ZUl5wwFtsY_2qeRiU_P2qOOJgu/view?usp=sharing

# https://www.martinfowler.com/books/eaa.html
# lab4 (EFCore)
```
dotnet new console -o lab4_entity_framework
cd lab4_entity_framework
```
# 刪除
```
package reference...
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
```
## sqlite
```xml!
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.10" />
</ItemGroup>
</Project>
```
# 加上一個.gitignore
```
bin/
obj/
Migrations/
```
# 創建git
```
git init
```
# 建立Model模型
## `Blog.cs`
```csharp
namespace Model;
public class Blog
{
public int BlogId { get; set; }
public String? Url { get; set; }
}
```
## `Post.cs`
```csharp
namespace Model;
public class Post
{
public int PostId { get; set; }
public String? Title { get; set; }
public String? Content { get; set; }
}
```
## `BlogContext.cs`
## 注意建構子要public
* `ctrl+.`
```csharp!
using Microsoft.EntityFrameworkCore;
namespace Model;
public class BlogContext : DbContext
{
public BlogContext()
{
var folder = Environment.SpecialFolder.LocalApplicationData;
var path = Environment.GetFolderPath(folder);
DbPath = System.IO.Path.Join(path, "lab4.db");
}
public DbSet<Blog>? Blogs { get; set; }
public DbSet<Post>? Posts { get; set; }
public string DbPath { get; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite($"Data Source={DbPath}");
}
```

```
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design
```
```
dotnet ef migrations add InitialCreate
dotnet ef migrations remove
dotnet ef database update
```
# 進入家目錄下的`\AppData\Local`
## 應該有lab4.db
# for MSSQL
## https://learn.microsoft.com/zh-tw/ef/core/dbcontext-configuration/
## https://sqlitebrowser.org/
## Program.cs
```csharp
using Model;
using var db = new BlogContext();
Console.WriteLine($"目前資料庫的路徑:{db.DbPath}");
Console.WriteLine($"新增數筆資料");
db.Add(new Blog { Url = "https://www.uuu.com.tw/" });
db.Add(new Blog { Url = "https://www.tibame.com/" });
db.Add(new Blog { Url = "https://hahow.in/" });
db.Add(new Blog { Url = "https://www.iii.org.tw/" });
db.SaveChanges();
Console.WriteLine("把資料讀回來");
var blogs = db.Blogs!.OrderBy(b => b.BlogId);
foreach (var b in blogs) {
Console.WriteLine($"blog id:{b.BlogId}, url是{b.Url}");
}
```
# Blog
```csharp
namespace Model;
public class Blog
{
public int BlogId { get; set; }
public String? Url { get; set; }
public List<Post> Posts { get; } = new();
}
```
# Post
```csharp!
namespace Model;
public class Post
{
public int PostId { get; set; }
public String? Title { get; set; }
public String? Content { get; set; }
public int BlogId {get;set;}
public Blog Blog {get;set;}=null!;
}
```
# dotnet build
```
dotnet ef migrations add BlogAddPost
dotnet ef database update
```
# 創建PK-->FK
```csharp
using Model;
using var db = new BlogContext();
Console.WriteLine($"目前資料庫的路徑:{db.DbPath}");
Console.WriteLine($"新增數筆資料");
db.Add(new Blog { Url = "https://www.uuu.com.tw/" });
db.Add(new Blog { Url = "https://www.tibame.com/" });
db.Add(new Blog { Url = "https://hahow.in/" });
db.Add(new Blog { Url = "https://www.iii.org.tw/" });
db.SaveChanges();
Console.WriteLine("把資料讀回來");
var blogs = db.Blogs!.OrderBy(b => b.BlogId);
foreach (var b in blogs)
{
Console.WriteLine($"blog id:{b.BlogId}, url是{b.Url}");
}
Console.WriteLine("準備修改");
var blog = db.Blogs!.OrderBy(b => b.BlogId).Last();
blog.Url = "https://www.cwb.gov.tw";
blog.Posts.Add(new Post { Title = "urgent news!", Content = "Typhoon is coming" });
db.SaveChanges();
Console.WriteLine("修改完成");
// 從主table往下讀
blogs = db.Blogs!.OrderBy(b => b.BlogId);
foreach (var b in blogs)
{
Console.WriteLine($"Blog ID={b.BlogId}, URL={b.Url}");
foreach (var p in b.Posts)
{
Console.WriteLine($"* title:{p.Title}, content:{p.Content}");
}
}
```
# lab4
* https://drive.google.com/file/d/1o8blhnca1pTbnE_Q2Do7Q7Q-6S7elMqx/view?usp=sharing
```
dotnet new mvc -o lab5_webmvc
dotnet build
dotnet run
```
## 在Controllers目錄下:
* `HelloWorldController.cs`
```csharp!
using Microsoft.AspNetCore.Mvc;
namespace lab5_webmvc;
public class HelloWorldController : Controller
{
public string Index() {
return "Index是預設的, 所以會對應到Controller類別的名稱";
}
public string Welcome() {
return "在Controller的後面可以接上welcome";
}
}
```
## https://localhost:7003/HelloWorld
## https://localhost:7003/HelloWorld/Welcome
```csharp
using Microsoft.AspNetCore.Mvc;
namespace lab5_webmvc;
public class HelloWorldController : Controller
{
public IActionResult Index() {
return View();
}
public string Welcome() {
return "在Controller的後面可以接上welcome";
}
}
```
## Views\HelloWorld
### Index.cshtml
```htmlembedded
<H2>Index</H2>
<p>直接讀取樣板</p>
```
# lab5
* https://drive.google.com/file/d/1Kykfe5VEQKDYRc0rSR9XVQcxnJucpReU/view?usp=sharing
# Day3
## 解決方案建立
```
dotnet new sln -o lab6_clean_architecture
cd lab6_clean_architecture
copy ../.gitignore .
git init
```
## 建立五個專案 (pp.8)
```
dotnet new webapi -o Together.Api
dotnet new classlib -o Together.Contract
dotnet new classlib -o Together.Infrastructure
dotnet new classlib -o Together.Domain
dotnet new classlib -o Together.Application
```

## 試著建置
```
cd Together.Api
dotnet build
```

# 把專案加到方案
```
cd lab6_clean_architecture
dotnet sln add (ls -r **\*.csproj)
```
# 增露api的相依性
## 在lab6根目錄
```
dotnet add .\Together.Api reference .\Together.Contract .\Together.Application .\Together.Infrastructure
```
```
cd lab6_clean_architecture\Together.Api
dotnet build
```
# Infrastructure <-- Application
```
dotnet add .\Together.Infrastructure reference .\Together.Application
```
# application <-- domain
```
dotnet add .\Together.Application reference .\Together.Domain
```
# step1 建立了DDD/clean architecture
* https://drive.google.com/file/d/1g8cpMG6ehZ3n8uVY2okIsSm985laoy48/view?usp=sharing
# 從方案執行某特定專案
```
dotnet run --project Together.Api
```
* https://localhost:7026/WeatherForecast
# 建立Rest下面的Sample目錄
## sample.http
```
GET https://localhost:7026/WeatherForecast
```
# clean up webapi的code
```csharp
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
// builder.Services.AddEndpointsApiExplorer();
// builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
// if (app.Environment.IsDevelopment())
// {
// app.UseSwagger();
// app.UseSwaggerUI();
// }
app.UseHttpsRedirection();
// app.UseAuthorization();
app.MapControllers();
app.Run();
```
# alt+shift+F 乾淨化程式
```csharp
var builder = WebApplication.CreateBuilder(args);
{
builder.Services.AddControllers();
}
var app = builder.Build();
{
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
}
```
```xml
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Together.Contract\Together.Contract.csproj" />
<ProjectReference Include="..\Together.Application\Together.Application.csproj" />
<ProjectReference Include="..\Together.Infrastructure\Together.Infrastructure.csproj" />
</ItemGroup>
</Project>
```
# step2 clean architecture, clean code
* https://drive.google.com/file/d/16Tmp8cZAJxcQRNFy435onQJ7WFLrYupi/view?usp=sharing
## Together.Api
### Controllers
* EventController.cs
```csharp!
using Microsoft.AspNetCore.Mvc;
namespace Together.Api.Controllers;
[ApiController]
[Route("api")]
public class EventController:ControllerBase
{
}
```
```
code .
```

# ctrl+.

# EventControllers.cs
```csharp
using Microsoft.AspNetCore.Mvc;
namespace Together.Api.Controllers;
[ApiController]
[Route("api")]
public class EventController : ControllerBase
{
[Route("add-event")]
public IActionResult AddEvent()
{
return Ok();
}
[Route("query-event")]
public IActionResult QueryEvent()
{
return Ok();
}
}
```
# sample.http
```
@REQUEST_SERVER = https://localhost:7026
### QUERY EVENT GET
GET {{REQUEST_SERVER}}/api/query-event
### ADD EEVENT GET
GET {{REQUEST_SERVER}}/api/add-event
```
# 應該看到的是200
```
HTTP/1.1 200 OK
Content-Length: 0
Connection: close
Date: Thu, 03 Nov 2022 03:34:03 GMT
Server: Kestrel
```
# Together.Contract.Controller
```
AddEventRequest.cs
```
# ctrl+P

```csharp
namespace Together.Contract.Controller;
public record QueryEventRequest(
float lat,
float len,
float length
);
```

# EventController.cs
```csharp
using Microsoft.AspNetCore.Mvc;
using Together.Contract.Controller;
namespace Together.Api.Controllers;
[ApiController]
[Route("api")]
public class EventController : ControllerBase
{
[Route("add-event")]
public IActionResult AddEvent(AddEventRequest request)
{
return Ok();
}
[Route("query-event")]
public IActionResult QueryEvent(QueryEventRequest request)
{
return Ok();
}
}
```
# https://drive.google.com/file/d/1bQWZA_Mi-fXF_IkJiPfHZE63wQPf2mIp/view?usp=sharing
# sample.http
```
@REQUEST_SERVER = https://localhost:7026
### QUERY EVENT GET
GET {{REQUEST_SERVER}}/api/query-event
Content-Type: application/json
{
"lat":20.4,
"lng":130.5,
"length":0.5
}
### ADD EEVENT GET
GET {{REQUEST_SERVER}}/api/add-event
Content-Type: application/json
{
"name":"拳擊有氧",
"coordinator":"Mark Ho",
"place":"星巴克三創",
"lat":20.4,
"lng":130.5,
"fee":500
}
```
# EventController.cs
```csharp
using Microsoft.AspNetCore.Mvc;
using Together.Contract.Controller;
namespace Together.Api.Controllers;
[ApiController]
[Route("api")]
public class EventController : ControllerBase
{
[Route("add-event")]
public IActionResult AddEvent(AddEventRequest request)
{
return Ok(request);
}
[Route("query-event")]
public IActionResult QueryEvent(QueryEventRequest request)
{
return Ok(request);
}
}
```
# AddEventResponse
```csharp
namespace Together.Contract.Controller;
public record AddEventResponse(
Guid Id,
string name,
string coordinator,
string place,
float lat,
float lng,
int fee
);
```
# QueryEventResponse.cs
```csharp
namespace Together.Contract.Controller;
public record QueryEventResponse (
string name,
string coordinator,
string place,
float lat,
float lng,
int fee
);
```
# EventController.cs
```csharp=
using Microsoft.AspNetCore.Mvc;
using Together.Contract.Controller;
namespace Together.Api.Controllers;
[ApiController]
[Route("api")]
public class EventController : ControllerBase
{
[HttpPost("add-event")]
public IActionResult AddEvent(AddEventRequest request)
{
AddEventResponse response = new AddEventResponse(
Guid.NewGuid(), request.name, request.coordinator, request.place,
request.lat, request.lng, request.fee);
return Ok(response);
}
[HttpPost("query-event")]
public IActionResult QueryEvent(QueryEventRequest request)
{
QueryEventResponse response = new QueryEventResponse("name", "coord", "tpe", 0.5f, 1.0f, 300);
QueryEventResponse[] events = new QueryEventResponse[]{response, response, response};
return Ok(events);
}
}
```

# step4
* https://drive.google.com/file/d/191iIQEPDS8nk-wBtQb16j25dRN2Vx-TT/view?usp=sharing
# Application層
# EventAddResult.cs
```csharp
namespace Together.Application.Services;
public record EventAddResult
(
Guid Id,
string name,
string coordinator,
string place,
float lat,
float lng,
int fee
);
```
# EventQueryResult.cs
```csharp=
namespace Together.Application.Services;
public record EventQueryResult(
string name,
string coordinator,
string place,
float lat,
float lng,
int fee
);
```
# IEventService.cs
```csharp=
namespace Together.Application.Services;
public interface IEventService
{
EventAddResult add(String name, String coordinator,
String place, float lat, float lng, int fee);
EventQueryResult[] query(float lat, float lng, float len);
}
```

# EventService.cs
```csharp=
namespace Together.Application.Services;
public class EventService : IEventService
{
public EventAddResult add(string name, string coordinator, string place, float lat, float lng, int fee)
{
return new EventAddResult(Guid.NewGuid(), name, coordinator, place, lat, lng, fee);
}
public EventQueryResult[] query(float lat, float lng, float len)
{
EventQueryResult r = new EventQueryResult("name", "coord", "tpe", 0.5f, 0.5f, 300);
EventQueryResult[] results = new EventQueryResult[] { r, r, r, r };
return results;
}
}
```

# https://drive.google.com/file/d/1JyUfA4dpdC3crMvaDBxzkVne4onLXrmN/view?usp=sharing
## Program.cs
```csharp=
using Together.Application.Services;
var builder = WebApplication.CreateBuilder(args);
{
builder.Services.AddControllers();
builder.Services.AddScoped<IEventService, EventService>();
}
var app = builder.Build();
{
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
}
```
# EventController.cs
```csharp
using Microsoft.AspNetCore.Mvc;
using Together.Application.Services;
using Together.Contract.Controller;
namespace Together.Api.Controllers;
[ApiController]
[Route("api")]
public class EventController : ControllerBase
{
private readonly IEventService eventService;
public EventController(IEventService eventService)
{
this.eventService = eventService;
}
[HttpPost("add-event")]
public IActionResult AddEvent(AddEventRequest request)
{
var result = eventService.add(request.name, request.coordinator,
request.place, request.lat, request.lng, request.fee);
AddEventResponse response = new AddEventResponse(result.Id,
result.name, result.coordinator, result.place, result.lat, result.lng, result.fee);
return Ok(response);
}
[HttpPost("query-event")]
public IActionResult QueryEvent(QueryEventRequest request)
{
var result = eventService.query(request.lat, request.length, request.length);
List<QueryEventResponse> events = new List<QueryEventResponse>();
foreach (var r in result)
{
QueryEventResponse response = new QueryEventResponse(r.name, r.coordinator,
r.place, r.lat, r.lng, r.fee);
events.Add(response);
}
return Ok(events.ToArray());
}
}
```
# step6
* https://drive.google.com/file/d/1pPVzQJrgi1GnhbxyYbTzbd4F9WuWkLFC/view?usp=sharing
# DependencyInjection.cs
```csharp=
using Microsoft.Extensions.DependencyInjection;
using Together.Application.Services;
namespace Together.Application;
public static class DependencyInjection
{
public static IServiceCollection AddApplication(this IServiceCollection services) {
services.AddScoped<IEventService, EventService>();
return services;
}
}
```
```
dotnet add .\Together.Application
package Microsoft.Extensions.DependencyInjection
```
# Program.cs
```csharp
using Together.Application;
var builder = WebApplication.CreateBuilder(args);
{
builder.Services.AddControllers();
builder.Services.AddApplication();
}
var app = builder.Build();
{
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
}
```
# step 7
* https://drive.google.com/file/d/1GbpHQSF3zOo06gEJc5NPFr_6N2j22pPE/view?usp=sharing
# Event.cs 在Domain的Entity下
```csharp=
namespace Together.Domain.Entity;
public class Event
{
public Guid Id { get; set; } = Guid.NewGuid();
public String? Name { get; set; } = null;
public String? Coordinator { get; set; } = null;
public String? Place { get; set; } = null;
public float Lat;
public float Lng;
public int Fee;
}
```

# Application\Common\Interfaces
## IEventRepository.cs
```csharp
using Together.Domain.Entity;
namespace Together.Application.Common.Interfaces;
public interface IEventRepository {
Event[] GetAll();
void AddEvent(Event e);
}
```
# Infrastructure\Persistence
## EventMemoryRepository.cs
```csharp!
using Together.Application.Common.Interfaces;
using Together.Domain.Entity;
namespace Together.Infrastructure.Persistence;
public class EventMemoryRepository : IEventRepository
{
private static readonly List<Event> _events = new();
public void AddEvent(Event e)
{
_events.Add(e);
}
public Event[] GetAll()
{
return _events.ToArray();
}
}
```
# step 8
* https://drive.google.com/file/d/1yFYWannKSGxYgmbNdohbDh3_Fub3vJTZ/view?usp=sharing
# Infrastructure下的DependencyInjection
```csharp
dotnet add .\Together.Infrastructure package Microsoft.Extensions.DependencyInjection
```
```
using Microsoft.Extensions.DependencyInjection;
using Together.Application.Common.Interfaces;
using Together.Infrastructure.Persistence;
namespace Together.Infrastructure;
public static class DependencyInjection {
public static IServiceCollection AddInfrastructure(this IServiceCollection services) {
services.AddScoped<IEventRepository, EventMemoryRepository>();
return services;
}
}
```
# EventService.cs
```csharp
using Together.Application.Common.Interfaces;
using Together.Domain.Entity;
namespace Together.Application.Services;
public class EventService : IEventService
{
private readonly IEventRepository repository;
public EventService(IEventRepository repository)
{
this.repository = repository;
}
public EventAddResult add(string name, string coordinator, string place, float lat, float lng, int fee)
{
var event1 = new Event { Name = name, Coordinator = coordinator, Place = place, Lat = lat, Lng = lng, Fee = fee };
repository.AddEvent(event1);
return new EventAddResult(Guid.NewGuid(), name, coordinator, place, lat, lng, fee);
}
public EventQueryResult[] query(float lat, float lng, float len)
{
List<EventQueryResult> results = new();
foreach (var r in repository.GetAll())
{
EventQueryResult result = new EventQueryResult(r.Name, r.Coordinator, r.Place, r.Lat, r.Lng, r.Fee);
results.Add(result);
}
return results.ToArray();
}
}
```
# Program.cs
```csharp
using Together.Application;
using Together.Infrastructure;
var builder = WebApplication.CreateBuilder(args);
{
builder.Services.AddControllers();
builder.Services.AddApplication();
builder.Services.AddInfrastructure();
}
var app = builder.Build();
{
app.UseHttpsRedirection();
app.MapControllers();
app.Run();
}
```
# step9
* https://drive.google.com/file/d/1JXQVNqu9WqonOZ-g0QytNFFh3xqiCIP-/view?usp=sharing
# EventQueryResult.cs
```csharp
namespace Together.Application.Services;
public record EventQueryResult(
string? name,
string? coordinator,
string? place,
float lat,
float lng,
int fee
);
```
# QueryEventResponse
```csharp
namespace Together.Contract.Controller;
public record QueryEventResponse (
string? name,
string? coordinator,
string? place,
float lat,
float lng,
int fee
);
```
```
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
cd ..
dotnet build
```
# EventContext.cs
```csharp
using Microsoft.EntityFrameworkCore;
using Together.Domain.Entity;
namespace Together.Infrastructure.Persistence;
public class EventContext : DbContext
{
public string DbPath { get; }
public EventContext()
{
var folder = Environment.SpecialFolder.LocalApplicationData;
var path = Environment.GetFolderPath(folder);
DbPath = System.IO.Path.Join(path, "lab6.db");
}
public DbSet<Event>? Events { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options) =>
options.UseSqlite($"Data Source={DbPath}");
}
```
# cd Together.Infrastructure
```
dotnet add package Microsoft.EntityFrameworkCore.Design
```
```
dotnet ef
migrations add InitialCreate
dotnet ef database update
```
# 進入`YOUR_HOME\AppData\Local`
# dir *.db
# EventEFCoreRepository
```csharp!
using Together.Application.Common.Interfaces;
using Together.Domain.Entity;
namespace Together.Infrastructure.Persistence;
public class EventEFCoreRepostiory : IEventRepository
{
private readonly EventContext db = new EventContext();
public void AddEvent(Event e)
{
db.Add(e);
db.SaveChanges();
}
public Event[] GetAll()
{
return db.Events!.ToArray();
}
}
```
# step10
* https://drive.google.com/file/d/1N_WxBirKoKif2cI-Xppd9X2Bw5VKehgr/view?usp=sharing