---
# System prepended metadata

title: 'DDD, C#,'

---

# 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
```

![](https://i.imgur.com/dQVOep4.png)

#### 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
```
![](https://i.imgur.com/6h8zwNo.png)



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

![](https://i.imgur.com/VXYY2oe.png)


### 額外使用的
#### 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

![](https://i.imgur.com/4LPHDry.png)

```
名稱: 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

![](https://i.imgur.com/LoIOekr.png)

![](https://i.imgur.com/2H6Ua9f.png)

![](https://i.imgur.com/IAW0QVo.png)

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

![](https://i.imgur.com/t5F8qaR.png)

# add projects to solution
```
dotnet sln add .\PrimeService\PrimeService.csproj
dotnet build
dotnet sln add .\PrimeService.Tests\PrimeService.Tests.csproj
dotnet build
dotnet test
```
# 加入一個專案
![](https://i.imgur.com/ynKIHfh.png)
# 加入兩個專案
![](https://i.imgur.com/YK7HfjG.png)
# 加入後
![](https://i.imgur.com/teglvmA.png)

```
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應該不是質數");
    }
}
```

![](https://i.imgur.com/YHF8s2p.png)

## ctrl+click點擊

![](https://i.imgur.com/ZOv8Vkq.png)

# git graph

![](https://i.imgur.com/tHFFdvW.png)

# ![](https://i.imgur.com/XuzOIXa.png)

# 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
```

![](https://i.imgur.com/GgQDBoH.png)

![](https://i.imgur.com/cY0OfWG.png)

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

![](https://i.imgur.com/xmR8tul.png)

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

![](https://i.imgur.com/J3TcWFf.png)


## 創建檔名為`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 ==>  啟動功能

![](https://i.imgur.com/bd2Cvd6.png)
```
<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+.`

![](https://i.imgur.com/Pt4Bqbt.png)

```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://i.imgur.com/uiirfBc.png)

# 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}");


}
```

![](https://i.imgur.com/hp0uk9F.png)

```
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
```
![](https://i.imgur.com/m1gFC6Y.png)

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

![](https://i.imgur.com/cUO5jNW.png)

# 把專案加到方案
```
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 .
```
![](https://i.imgur.com/9WbpSX8.png)

# ctrl+.
![](https://i.imgur.com/o4ldUWa.png)

# 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

![](https://i.imgur.com/wMmCMv3.png)

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

![](https://i.imgur.com/pbXPOBR.png)
# 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);
    }
}
```

![](https://i.imgur.com/xHG83BG.png)

# 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);
}

```

![](https://i.imgur.com/rlwp0zi.png)


# 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://i.imgur.com/TS1EMY5.png)

# 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;

}
```
![](https://i.imgur.com/dzazH7p.png)
# 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

