diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/DesignTimeBuild/.dtbcache.v2 b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/DesignTimeBuild/.dtbcache.v2 similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/DesignTimeBuild/.dtbcache.v2 rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/DesignTimeBuild/.dtbcache.v2 diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/358bcc67-b3e5-4cd2-9984-3aecd4842c87.vsidx b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/358bcc67-b3e5-4cd2-9984-3aecd4842c87.vsidx similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/358bcc67-b3e5-4cd2-9984-3aecd4842c87.vsidx rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/358bcc67-b3e5-4cd2-9984-3aecd4842c87.vsidx diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/99aeb7ce-2563-4631-b966-40de4255c41b.vsidx b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/99aeb7ce-2563-4631-b966-40de4255c41b.vsidx similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/99aeb7ce-2563-4631-b966-40de4255c41b.vsidx rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/99aeb7ce-2563-4631-b966-40de4255c41b.vsidx diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/d07aa008-5d90-4a0f-91a4-fd404b9f6842.vsidx b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/d07aa008-5d90-4a0f-91a4-fd404b9f6842.vsidx similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/d07aa008-5d90-4a0f-91a4-fd404b9f6842.vsidx rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/FileContentIndex/d07aa008-5d90-4a0f-91a4-fd404b9f6842.vsidx diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/v17/.futdcache.v2 b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/v17/.futdcache.v2 similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/v17/.futdcache.v2 rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/v17/.futdcache.v2 diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/v17/.suo b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/v17/.suo similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/v17/.suo rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/v17/.suo diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/v17/DocumentLayout.backup.json b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/v17/DocumentLayout.backup.json similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/v17/DocumentLayout.backup.json rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/v17/DocumentLayout.backup.json diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/v17/DocumentLayout.json b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/v17/DocumentLayout.json similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/DILastSession/v17/DocumentLayout.json rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/DILastSession/v17/DocumentLayout.json diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.metadata.v9.bin b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.metadata.v9.bin similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.metadata.v9.bin rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.metadata.v9.bin diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.projects.v9.bin b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.projects.v9.bin similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.projects.v9.bin rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.projects.v9.bin diff --git a/01_IntroductionSessions/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.strings.v9.bin b/01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.strings.v9.bin similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.strings.v9.bin rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/.vs/ProjectEvaluation/dilastsession.strings.v9.bin diff --git a/01_IntroductionSessions/DILastSession/DILastSession/DILastSession.csproj b/01_IntroductionSessions/Session07/DILastSession/DILastSession/DILastSession.csproj similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/DILastSession.csproj rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/DILastSession.csproj diff --git a/01_IntroductionSessions/DILastSession/DILastSession/DILastSession.sln b/01_IntroductionSessions/Session07/DILastSession/DILastSession/DILastSession.sln similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/DILastSession.sln rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/DILastSession.sln diff --git a/01_IntroductionSessions/DILastSession/DILastSession/ExternalService/Service01.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/ExternalService/Service01.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/ExternalService/Service01.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/ExternalService/Service01.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/ExternalService/Service02.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/ExternalService/Service02.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/ExternalService/Service02.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/ExternalService/Service02.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/ExternalService/Service03.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/ExternalService/Service03.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/ExternalService/Service03.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/ExternalService/Service03.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/Framework/Base/BaseService.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/Framework/Base/BaseService.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/Framework/Base/BaseService.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/Framework/Base/BaseService.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/Framework/Interface/IService.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/Framework/Interface/IService.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/Framework/Interface/IService.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/Framework/Interface/IService.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/LifeCycle/A.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/LifeCycle/A.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/LifeCycle/A.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/LifeCycle/A.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/LifeCycle/B.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/LifeCycle/B.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/LifeCycle/B.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/LifeCycle/B.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/LifeCycle/C.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/LifeCycle/C.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/LifeCycle/C.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/LifeCycle/C.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/Program.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/Program.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/Program.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/Program.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.deps.json b/01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.deps.json similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.deps.json rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.deps.json diff --git a/01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.dll b/01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.dll similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.dll rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.dll diff --git a/01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.exe b/01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.exe rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.exe diff --git a/01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.pdb b/01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.pdb rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.pdb diff --git a/01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.runtimeconfig.json b/01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.runtimeconfig.json similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.runtimeconfig.json rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/bin/Debug/net8.0/DILastSession.runtimeconfig.json diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.dgspec.json b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.dgspec.json similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.dgspec.json rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.dgspec.json diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.g.props b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.g.props similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.g.props rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.g.props diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.g.targets b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.g.targets similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.g.targets rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/DILastSession.csproj.nuget.g.targets diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.AssemblyInfo.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.AssemblyInfo.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.AssemblyInfo.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.AssemblyInfo.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.AssemblyInfoInputs.cache b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.AssemblyInfoInputs.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.AssemblyInfoInputs.cache rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.AssemblyInfoInputs.cache diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.GeneratedMSBuildEditorConfig.editorconfig b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.GeneratedMSBuildEditorConfig.editorconfig similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.GeneratedMSBuildEditorConfig.editorconfig rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.GeneratedMSBuildEditorConfig.editorconfig diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.GlobalUsings.g.cs b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.GlobalUsings.g.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.GlobalUsings.g.cs rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.GlobalUsings.g.cs diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.assets.cache b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.assets.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.assets.cache rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.assets.cache diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.BuildWithSkipAnalyzers b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.BuildWithSkipAnalyzers similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.BuildWithSkipAnalyzers rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.BuildWithSkipAnalyzers diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.CoreCompileInputs.cache b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.CoreCompileInputs.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.CoreCompileInputs.cache rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.CoreCompileInputs.cache diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.FileListAbsolute.txt b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.FileListAbsolute.txt similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.FileListAbsolute.txt rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.csproj.FileListAbsolute.txt diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.dll b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.dll similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.dll rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.dll diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.genruntimeconfig.cache b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.genruntimeconfig.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.genruntimeconfig.cache rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.genruntimeconfig.cache diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.pdb b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.pdb rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.pdb diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.sourcelink.json b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.sourcelink.json similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.sourcelink.json rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/DILastSession.sourcelink.json diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/apphost.exe b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/apphost.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/apphost.exe rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/apphost.exe diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/ref/DILastSession.dll b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/ref/DILastSession.dll similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/ref/DILastSession.dll rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/ref/DILastSession.dll diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/refint/DILastSession.dll b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/refint/DILastSession.dll similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/Debug/net8.0/refint/DILastSession.dll rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/Debug/net8.0/refint/DILastSession.dll diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/project.assets.json b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/project.assets.json similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/project.assets.json rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/project.assets.json diff --git a/01_IntroductionSessions/DILastSession/DILastSession/obj/project.nuget.cache b/01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/project.nuget.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession/obj/project.nuget.cache rename to 01_IntroductionSessions/Session07/DILastSession/DILastSession/obj/project.nuget.cache diff --git a/01_IntroductionSessions/DILastSession/Session Notes.txt b/01_IntroductionSessions/Session07/DILastSession/Session Notes.txt similarity index 100% rename from 01_IntroductionSessions/DILastSession/Session Notes.txt rename to 01_IntroductionSessions/Session07/DILastSession/Session Notes.txt diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/FileContentIndex/794c0bb5-712e-4ca0-a462-b9205f93f5e5.vsidx b/01_IntroductionSessions/Session07/Projects/.vs/Session07/FileContentIndex/794c0bb5-712e-4ca0-a462-b9205f93f5e5.vsidx similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/FileContentIndex/794c0bb5-712e-4ca0-a462-b9205f93f5e5.vsidx rename to 01_IntroductionSessions/Session07/Projects/.vs/Session07/FileContentIndex/794c0bb5-712e-4ca0-a462-b9205f93f5e5.vsidx diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/FileContentIndex/ec0a0821-a410-4fd0-ad0d-393b5ba9f39b.vsidx b/01_IntroductionSessions/Session07/Projects/.vs/Session07/FileContentIndex/ec0a0821-a410-4fd0-ad0d-393b5ba9f39b.vsidx similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/FileContentIndex/ec0a0821-a410-4fd0-ad0d-393b5ba9f39b.vsidx rename to 01_IntroductionSessions/Session07/Projects/.vs/Session07/FileContentIndex/ec0a0821-a410-4fd0-ad0d-393b5ba9f39b.vsidx diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/v16/.suo b/01_IntroductionSessions/Session07/Projects/.vs/Session07/v16/.suo similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/v16/.suo rename to 01_IntroductionSessions/Session07/Projects/.vs/Session07/v16/.suo diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/v17/.suo b/01_IntroductionSessions/Session07/Projects/.vs/Session07/v17/.suo similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/v17/.suo rename to 01_IntroductionSessions/Session07/Projects/.vs/Session07/v17/.suo diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/v17/DocumentLayout.backup.json b/01_IntroductionSessions/Session07/Projects/.vs/Session07/v17/DocumentLayout.backup.json similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/v17/DocumentLayout.backup.json rename to 01_IntroductionSessions/Session07/Projects/.vs/Session07/v17/DocumentLayout.backup.json diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/v17/DocumentLayout.json b/01_IntroductionSessions/Session07/Projects/.vs/Session07/v17/DocumentLayout.json similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/.vs/Session07/v17/DocumentLayout.json rename to 01_IntroductionSessions/Session07/Projects/.vs/Session07/v17/DocumentLayout.json diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01.rar b/01_IntroductionSessions/Session07/Projects/DIP_Solution01.rar similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01.rar rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01.rar diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01.zip b/01_IntroductionSessions/Session07/Projects/DIP_Solution01.zip similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01.zip rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01.zip diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/App.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/App.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/App.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/App.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/DIP_Solution01.csproj b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/DIP_Solution01.csproj similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/DIP_Solution01.csproj rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/DIP_Solution01.csproj diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/ExternalService/Service01.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/ExternalService/Service01.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/ExternalService/Service01.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/ExternalService/Service01.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/ExternalService/Service02.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/ExternalService/Service02.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/ExternalService/Service02.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/ExternalService/Service02.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/ExternalService/Service03.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/ExternalService/Service03.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/ExternalService/Service03.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/ExternalService/Service03.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/LifeCycle/A.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/LifeCycle/A.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/LifeCycle/A.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/LifeCycle/A.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/LifeCycle/B.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/LifeCycle/B.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/LifeCycle/B.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/LifeCycle/B.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/LifeCycle/C.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/LifeCycle/C.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/LifeCycle/C.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/LifeCycle/C.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/Program.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/Program.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/Program.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/Program.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/Properties/AssemblyInfo.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/Properties/AssemblyInfo.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/Properties/AssemblyInfo.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/Properties/AssemblyInfo.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/bin/Debug/DIP_Solution01.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/bin/Debug/DIP_Solution01.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/bin/Debug/DIP_Solution01.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/bin/Debug/DIP_Solution01.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/bin/Debug/DIP_Solution01.exe.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/bin/Debug/DIP_Solution01.exe.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/bin/Debug/DIP_Solution01.exe.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/bin/Debug/DIP_Solution01.exe.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/bin/Debug/DIP_Solution01.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/bin/Debug/DIP_Solution01.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/bin/Debug/DIP_Solution01.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/bin/Debug/DIP_Solution01.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.AssemblyReference.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.AssemblyReference.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.AssemblyReference.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.AssemblyReference.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.CoreCompileInputs.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.CoreCompileInputs.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.CoreCompileInputs.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.CoreCompileInputs.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.FileListAbsolute.txt b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.FileListAbsolute.txt similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.FileListAbsolute.txt rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.csproj.FileListAbsolute.txt diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DIP_Solution01.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DIP_Solution01.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution01/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution01/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/App.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/App.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/App.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/App.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/DIP_Solution02.csproj b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/DIP_Solution02.csproj similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/DIP_Solution02.csproj rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/DIP_Solution02.csproj diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/ExternalService/Service01.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/ExternalService/Service01.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/ExternalService/Service01.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/ExternalService/Service01.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/ExternalService/Service02.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/ExternalService/Service02.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/ExternalService/Service02.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/ExternalService/Service02.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/ExternalService/Service03.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/ExternalService/Service03.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/ExternalService/Service03.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/ExternalService/Service03.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/LifeCycle/A.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/LifeCycle/A.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/LifeCycle/A.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/LifeCycle/A.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/LifeCycle/B.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/LifeCycle/B.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/LifeCycle/B.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/LifeCycle/B.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/LifeCycle/C.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/LifeCycle/C.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/LifeCycle/C.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/LifeCycle/C.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/Program.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/Program.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/Program.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/Program.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/Properties/AssemblyInfo.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/Properties/AssemblyInfo.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/Properties/AssemblyInfo.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/Properties/AssemblyInfo.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/bin/Debug/DIP_Solution02.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/bin/Debug/DIP_Solution02.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/bin/Debug/DIP_Solution02.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/bin/Debug/DIP_Solution02.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/bin/Debug/DIP_Solution02.exe.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/bin/Debug/DIP_Solution02.exe.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/bin/Debug/DIP_Solution02.exe.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/bin/Debug/DIP_Solution02.exe.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/bin/Debug/DIP_Solution02.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/bin/Debug/DIP_Solution02.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/bin/Debug/DIP_Solution02.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/bin/Debug/DIP_Solution02.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.AssemblyReference.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.AssemblyReference.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.AssemblyReference.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.AssemblyReference.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.CoreCompileInputs.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.CoreCompileInputs.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.CoreCompileInputs.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.CoreCompileInputs.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.FileListAbsolute.txt b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.FileListAbsolute.txt similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.FileListAbsolute.txt rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.csproj.FileListAbsolute.txt diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DIP_Solution02.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DIP_Solution02.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution02/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution02/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03.zip b/01_IntroductionSessions/Session07/Projects/DIP_Solution03.zip similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03.zip rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03.zip diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/App.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/App.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/App.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/App.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/DIP_Solution03.csproj b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/DIP_Solution03.csproj similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/DIP_Solution03.csproj rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/DIP_Solution03.csproj diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/ExternalService/Service01.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/ExternalService/Service01.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/ExternalService/Service01.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/ExternalService/Service01.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/ExternalService/Service02.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/ExternalService/Service02.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/ExternalService/Service02.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/ExternalService/Service02.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/ExternalService/Service03.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/ExternalService/Service03.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/ExternalService/Service03.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/ExternalService/Service03.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/LifeCycle/A.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/LifeCycle/A.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/LifeCycle/A.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/LifeCycle/A.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/LifeCycle/B.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/LifeCycle/B.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/LifeCycle/B.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/LifeCycle/B.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/LifeCycle/C.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/LifeCycle/C.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/LifeCycle/C.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/LifeCycle/C.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/Program.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/Program.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/Program.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/Program.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/Properties/AssemblyInfo.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/Properties/AssemblyInfo.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/Properties/AssemblyInfo.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/Properties/AssemblyInfo.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/Service.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/Service.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/Service.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/Service.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/bin/Debug/DIP_Solution03.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/bin/Debug/DIP_Solution03.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/bin/Debug/DIP_Solution03.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/bin/Debug/DIP_Solution03.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/bin/Debug/DIP_Solution03.exe.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/bin/Debug/DIP_Solution03.exe.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/bin/Debug/DIP_Solution03.exe.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/bin/Debug/DIP_Solution03.exe.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/bin/Debug/DIP_Solution03.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/bin/Debug/DIP_Solution03.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/bin/Debug/DIP_Solution03.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/bin/Debug/DIP_Solution03.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.AssemblyReference.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.AssemblyReference.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.AssemblyReference.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.AssemblyReference.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.CoreCompileInputs.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.CoreCompileInputs.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.CoreCompileInputs.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.CoreCompileInputs.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.FileListAbsolute.txt b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.FileListAbsolute.txt similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.FileListAbsolute.txt rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.csproj.FileListAbsolute.txt diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DIP_Solution03.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DIP_Solution03.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution03/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution03/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/App.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/App.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/App.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/App.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/DIP_Solution04.csproj b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/DIP_Solution04.csproj similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/DIP_Solution04.csproj rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/DIP_Solution04.csproj diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/ExternalService/Service01.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/ExternalService/Service01.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/ExternalService/Service01.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/ExternalService/Service01.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/ExternalService/Service02.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/ExternalService/Service02.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/ExternalService/Service02.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/ExternalService/Service02.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/ExternalService/Service03.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/ExternalService/Service03.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/ExternalService/Service03.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/ExternalService/Service03.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/Framework/Base/BaseService.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/Framework/Base/BaseService.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/Framework/Base/BaseService.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/Framework/Base/BaseService.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/Framework/Interface/IService.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/Framework/Interface/IService.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/Framework/Interface/IService.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/Framework/Interface/IService.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/LifeCycle/A.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/LifeCycle/A.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/LifeCycle/A.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/LifeCycle/A.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/LifeCycle/B.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/LifeCycle/B.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/LifeCycle/B.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/LifeCycle/B.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/LifeCycle/C.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/LifeCycle/C.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/LifeCycle/C.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/LifeCycle/C.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/Program.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/Program.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/Program.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/Program.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/Properties/AssemblyInfo.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/Properties/AssemblyInfo.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/Properties/AssemblyInfo.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/Properties/AssemblyInfo.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/bin/Debug/DIP_Solution04.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/bin/Debug/DIP_Solution04.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/bin/Debug/DIP_Solution04.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/bin/Debug/DIP_Solution04.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/bin/Debug/DIP_Solution04.exe.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/bin/Debug/DIP_Solution04.exe.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/bin/Debug/DIP_Solution04.exe.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/bin/Debug/DIP_Solution04.exe.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/bin/Debug/DIP_Solution04.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/bin/Debug/DIP_Solution04.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/bin/Debug/DIP_Solution04.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/bin/Debug/DIP_Solution04.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.AssemblyReference.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.AssemblyReference.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.AssemblyReference.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.AssemblyReference.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.CoreCompileInputs.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.CoreCompileInputs.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.CoreCompileInputs.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.CoreCompileInputs.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.FileListAbsolute.txt b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.FileListAbsolute.txt similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.FileListAbsolute.txt rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.csproj.FileListAbsolute.txt diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DIP_Solution04.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DIP_Solution04.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution04/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution04/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/App.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/App.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/App.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/App.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/DIP_Solution05.csproj b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/DIP_Solution05.csproj similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/DIP_Solution05.csproj rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/DIP_Solution05.csproj diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/ExternalService/Service01.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/ExternalService/Service01.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/ExternalService/Service01.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/ExternalService/Service01.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/ExternalService/Service02.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/ExternalService/Service02.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/ExternalService/Service02.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/ExternalService/Service02.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/ExternalService/Service03.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/ExternalService/Service03.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/ExternalService/Service03.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/ExternalService/Service03.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/Framework/Base/BaseService.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/Framework/Base/BaseService.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/Framework/Base/BaseService.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/Framework/Base/BaseService.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/Framework/Interface/IService.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/Framework/Interface/IService.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/Framework/Interface/IService.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/Framework/Interface/IService.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/LifeCycle/A.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/LifeCycle/A.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/LifeCycle/A.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/LifeCycle/A.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/LifeCycle/B.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/LifeCycle/B.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/LifeCycle/B.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/LifeCycle/B.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/LifeCycle/C.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/LifeCycle/C.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/LifeCycle/C.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/LifeCycle/C.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/Program.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/Program.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/Program.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/Program.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/Properties/AssemblyInfo.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/Properties/AssemblyInfo.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/Properties/AssemblyInfo.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/Properties/AssemblyInfo.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/bin/Debug/DIP_Solution05.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/bin/Debug/DIP_Solution05.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/bin/Debug/DIP_Solution05.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/bin/Debug/DIP_Solution05.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/bin/Debug/DIP_Solution05.exe.config b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/bin/Debug/DIP_Solution05.exe.config similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/bin/Debug/DIP_Solution05.exe.config rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/bin/Debug/DIP_Solution05.exe.config diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/bin/Debug/DIP_Solution05.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/bin/Debug/DIP_Solution05.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/bin/Debug/DIP_Solution05.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/bin/Debug/DIP_Solution05.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/.NETFramework,Version=v4.7.2.AssemblyAttributes.cs diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.AssemblyReference.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.AssemblyReference.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.AssemblyReference.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.AssemblyReference.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.CoreCompileInputs.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.CoreCompileInputs.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.CoreCompileInputs.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.CoreCompileInputs.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.FileListAbsolute.txt b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.FileListAbsolute.txt similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.FileListAbsolute.txt rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.csproj.FileListAbsolute.txt diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.exe b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.exe similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.exe rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.exe diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.pdb b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.pdb similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DIP_Solution05.pdb rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DIP_Solution05.pdb diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/DIP_Solution05/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache rename to 01_IntroductionSessions/Session07/Projects/DIP_Solution05/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache diff --git a/01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/Session07.sln b/01_IntroductionSessions/Session07/Projects/Session07.sln similarity index 100% rename from 01_IntroductionSessions/DILastSession/ALI_Session07/Session07/Session07/Session07.sln rename to 01_IntroductionSessions/Session07/Projects/Session07.sln diff --git a/01_IntroductionSessions/DILastSession/DILastSession.md b/01_IntroductionSessions/Session07/Session07.md similarity index 100% rename from 01_IntroductionSessions/DILastSession/DILastSession.md rename to 01_IntroductionSessions/Session07/Session07.md diff --git a/02_ProjectOrientedSessions/Session00/ProjectStructure.md b/02_ProjectOrientedSessions/Session00/Project Structure.md similarity index 97% rename from 02_ProjectOrientedSessions/Session00/ProjectStructure.md rename to 02_ProjectOrientedSessions/Session00/Project Structure.md index bde5ff2..20aa49e 100644 --- a/02_ProjectOrientedSessions/Session00/ProjectStructure.md +++ b/02_ProjectOrientedSessions/Session00/Project Structure.md @@ -37,7 +37,6 @@ Clean Architecture consists of **four main layers**: } } ``` - --- @@ -213,6 +212,8 @@ This ensures the **business logic is central** and **not coupled** to frameworks - Domain Project - Packages: - AutoMapper + - Microsoft.AspNetCore.Authentication.JwtBearer + - System.IdentityModel.Tokens.Jwt - Microsoft.EntityFrameworkCore.Design - Microsoft.EntityFrameworkCore.SqlServer - Microsoft.EntityFrameworkCore.Tools @@ -273,6 +274,9 @@ This ensures the **business logic is central** and **not coupled** to frameworks - Domain Project - Packages: - Microsoft.EntityFrameworkCore.SqlServer + - Microsoft.EntityFrameworkCore.Design + - Microsoft.EntityFrameworkCore.Proxies + - Microsoft.EntityFrameworkCore.Tools --- ### **Additional Projects (Optional)** @@ -281,8 +285,3 @@ This ensures the **business logic is central** and **not coupled** to frameworks - 📂 `MyApp.Shared` – Shared utilities (cross-cutting concerns like constants, helpers). -# Frontend Project Structure (Will most likely change in future) - -```shell -npx create-react-app alibabaclone-frontend --use-npm --template typescript cd alibabaclone-frontend npm start -``` \ No newline at end of file diff --git a/02_ProjectOrientedSessions/Session01/Session 01 Document.md b/02_ProjectOrientedSessions/Session01/Session01 Additional Info.md similarity index 57% rename from 02_ProjectOrientedSessions/Session01/Session 01 Document.md rename to 02_ProjectOrientedSessions/Session01/Session01 Additional Info.md index eaa4707..361fba5 100644 --- a/02_ProjectOrientedSessions/Session01/Session 01 Document.md +++ b/02_ProjectOrientedSessions/Session01/Session01 Additional Info.md @@ -1,159 +1,3 @@ -## Branching -- [ ] Create the develop branch -- [ ] Create the feature/domain-entities branch based on develop - -## `IEntity.cs` -- [ ] Create the IEntity **interface** - -> Location: Domain Project > Framework > Interfaces -```C# -public interface IEntity -{ - public TKey Id { get; set; } -} -``` -## `Entity.cs` -- [ ] Create the Entity **class** - -> Location: Domain Project > Framework > Base -```C# -public class Entity : IEntity -{ - public TKey Id{ get; set; } -} -``` - -### Why do we need IEntity and Entity? (Chat GPT): -> this approach is **valid and commonly used** in **Domain-Driven Design (DDD)** and **Clean Architecture**. It provides **consistency**, **reusability**, and **common functionality** across all entities. -## Create Entities -> Location: Domain Project > Aggregates > (RelatedFolder) - -### They all (with the exception of join tables) should inherit Entity, and you should specify the datatype of the Id -### Use the latest version of ERD to specify the properties -### You can use this project as a reference: -https://github.com/MehrdadShirvani/AlibabaClone-Backend/tree/develop/AlibabaClone.Domain/Aggregates -### Link to the ERD: -https://github.com/TheOrderOfPhoenix/ASP.NET/tree/main/02_ProjectOrientedSessions/docs - -### One Example: - -```C# -public class Account : Entity -{ - public required string PhoneNumber { get; set; } - public required string Password { set; get; } - public string? Email { get; set; } - public long? PersonId { get; set; } -} -``` - -## Add Navigation Properties -### What is a navigation property? (the following pieces of code are just there for educational purposes) -#### **🔹 Navigation Properties in Entity Framework Core: Everything You Need to Know** - ---- - -#### **📌 What Are Navigation Properties?** - -Navigation properties in Entity Framework Core (EF Core) **represent relationships between entities**. They allow you to **navigate** (follow) the relationships between different tables using **C# objects** instead of writing SQL joins manually. - -For example, if you have a **Ticket** entity related to a **Buyer**, the navigation property allows you to access the buyer from a ticket without writing a separate SQL query. - ---- - -#### **🔹 Types of Navigation Properties** - -Navigation properties can be of two types: - -| Relationship Type | Description | -| ---------------------------------- | ----------------------------------------------------------------------------- | -| **Reference Navigation Property** | Represents a **single entity** related to another (one-to-one or many-to-one) | -| **Collection Navigation Property** | Represents **a list of related entities** (one-to-many or many-to-many) | - ---- - -#### **🔹 How to Define Navigation Properties?** - -##### **🔹 One-to-Many Example** - -A **Buyer** can have **multiple Tickets**, but each **Ticket** belongs to one **Buyer**. - -```csharp -public class Buyer -{ - public int Id { get; set; } - public string Name { get; set; } - - // Navigation Property (One Buyer → Many Tickets) - public virtual ICollection Tickets { get; set; } = new List(); -} - -public class Ticket -{ - public int Id { get; set; } - public int BuyerId { get; set; } - - // Navigation Property (Many Tickets → One Buyer) - public virtual Buyer Buyer { get; set; } -} -``` - -##### **🔹 One-to-One Example** - -A **Ticket** can have only **one Transaction**, and a **Transaction** belongs to exactly **one Ticket**. - -```csharp -public class Ticket -{ - public int Id { get; set; } - - // One-to-One Navigation Property - public virtual Transaction Transaction { get; set; } -} - -public class Transaction -{ - public int Id { get; set; } - public int TicketId { get; set; } - - // One-to-One Navigation Property - public virtual Ticket Ticket { get; set; } -} -``` - -##### **🔹 Many-to-Many Example** - -A **Buyer** can buy **many Tickets**, and each **Ticket** can be bought by **many Buyers** (if resale is allowed). - -```csharp -public class Buyer -{ - public int Id { get; set; } - public string Name { get; set; } - - // Many-to-Many Navigation Property - public virtual ICollection Tickets { get; set; } = new List(); -} - -public class Ticket -{ - public int Id { get; set; } - - // Many-to-Many Navigation Property - public virtual ICollection Buyers { get; set; } = new List(); -} -``` - -### Add the needed navigation properties inside entities -- [ ] Figure out what navigation properties are needed based on the ERD, and use this project as a reference: -https://github.com/MehrdadShirvani/AlibabaClone-Backend/tree/develop/AlibabaClone.Domain/Aggregates -- [ ] Don't forget to mark all the navigation properties as `virtual` - -## Add a NuGet package to Infrastructure Project -- [ ] Add `Microsoft.EntityFrameworkCore.Proxies` to Infrastructure Project -## Create a pull request and merge the current branch with develop - -# Side Notes ## **Choosing the right datatype for integer values, specially IDs (Chat GPT):** ### **1️⃣ Integer Data Types (int, short, long) in C# and SQL Server** diff --git a/02_ProjectOrientedSessions/Session01/Session01 Backend.md b/02_ProjectOrientedSessions/Session01/Session01 Backend.md new file mode 100644 index 0000000..02289a7 --- /dev/null +++ b/02_ProjectOrientedSessions/Session01/Session01 Backend.md @@ -0,0 +1,156 @@ +# Branching +- [ ] Create the develop branch +- [ ] Create the feature/domain-entities branch based on develop + +# `IEntity.cs` +- [ ] Create the IEntity **interface** + +> Location: Domain Project > Framework > Interfaces +```C# +public interface IEntity +{ + public TKey Id { get; set; } +} +``` +# `Entity.cs` +- [ ] Create the Entity **class** + +> Location: Domain Project > Framework > Base +```C# +public class Entity : IEntity +{ + public TKey Id{ get; set; } +} +``` + +### Why do we need IEntity and Entity? (Chat GPT): +> this approach is **valid and commonly used** in **Domain-Driven Design (DDD)** and **Clean Architecture**. It provides **consistency**, **reusability**, and **common functionality** across all entities. +# Create Entities +> Location: Domain Project > Aggregates > (RelatedFolder) + +### They all (with the exception of join tables) should inherit Entity, and you should specify the datatype of the Id +### Use the latest version of ERD to specify the properties +### You can use this project as a reference: +https://github.com/MehrdadShirvani/AlibabaClone-Backend/tree/develop/AlibabaClone.Domain/Aggregates +### Link to the ERD: +https://github.com/TheOrderOfPhoenix/ASP.NET/tree/main/02_ProjectOrientedSessions/docs + +### One Example: + +```C# +public class Account : Entity +{ + public required string PhoneNumber { get; set; } + public required string Password { set; get; } + public string? Email { get; set; } + public long? PersonId { get; set; } +} +``` + +# Add Navigation Properties +### What is a navigation property? (the following pieces of code are just there for educational purposes) +#### **🔹 Navigation Properties in Entity Framework Core: Everything You Need to Know** + +--- + +#### **📌 What Are Navigation Properties?** + +Navigation properties in Entity Framework Core (EF Core) **represent relationships between entities**. They allow you to **navigate** (follow) the relationships between different tables using **C# objects** instead of writing SQL joins manually. + +For example, if you have a **Ticket** entity related to a **Buyer**, the navigation property allows you to access the buyer from a ticket without writing a separate SQL query. + +--- + +#### **🔹 Types of Navigation Properties** + +Navigation properties can be of two types: + +| Relationship Type | Description | +| ---------------------------------- | ----------------------------------------------------------------------------- | +| **Reference Navigation Property** | Represents a **single entity** related to another (one-to-one or many-to-one) | +| **Collection Navigation Property** | Represents **a list of related entities** (one-to-many or many-to-many) | + +--- + +#### **🔹 How to Define Navigation Properties?** + +##### **🔹 One-to-Many Example** + +A **Buyer** can have **multiple Tickets**, but each **Ticket** belongs to one **Buyer**. + +```csharp +public class Buyer +{ + public int Id { get; set; } + public string Name { get; set; } + + // Navigation Property (One Buyer → Many Tickets) + public virtual ICollection Tickets { get; set; } = new List(); +} + +public class Ticket +{ + public int Id { get; set; } + public int BuyerId { get; set; } + + // Navigation Property (Many Tickets → One Buyer) + public virtual Buyer Buyer { get; set; } +} +``` + +##### **🔹 One-to-One Example** + +A **Ticket** can have only **one Transaction**, and a **Transaction** belongs to exactly **one Ticket**. + +```csharp +public class Ticket +{ + public int Id { get; set; } + + // One-to-One Navigation Property + public virtual Transaction Transaction { get; set; } +} + +public class Transaction +{ + public int Id { get; set; } + public int TicketId { get; set; } + + // One-to-One Navigation Property + public virtual Ticket Ticket { get; set; } +} +``` + +##### **🔹 Many-to-Many Example** + +A **Buyer** can buy **many Tickets**, and each **Ticket** can be bought by **many Buyers** (if resale is allowed). + +```csharp +public class Buyer +{ + public int Id { get; set; } + public string Name { get; set; } + + // Many-to-Many Navigation Property + public virtual ICollection Tickets { get; set; } = new List(); +} + +public class Ticket +{ + public int Id { get; set; } + + // Many-to-Many Navigation Property + public virtual ICollection Buyers { get; set; } = new List(); +} +``` + +### Add the needed navigation properties inside entities +- [ ] Figure out what navigation properties are needed based on the ERD, and use this project as a reference: +https://github.com/MehrdadShirvani/AlibabaClone-Backend/tree/develop/AlibabaClone.Domain/Aggregates +- [ ] Don't forget to mark all the navigation properties as `virtual` + +# Add Packages to Infrastructure Project +- [ ] Add `Microsoft.EntityFrameworkCore.Proxies` to Infrastructure Project +# Merge +- [ ] Create a PR and merge the current branch with develop + diff --git a/02_ProjectOrientedSessions/Session01/Session 01 Preparation.md b/02_ProjectOrientedSessions/Session01/Session01 Preparation.md similarity index 95% rename from 02_ProjectOrientedSessions/Session01/Session 01 Preparation.md rename to 02_ProjectOrientedSessions/Session01/Session01 Preparation.md index 642b965..8cdee6b 100644 --- a/02_ProjectOrientedSessions/Session01/Session 01 Preparation.md +++ b/02_ProjectOrientedSessions/Session01/Session01 Preparation.md @@ -14,7 +14,7 @@ Meditates between the domain and data mapping layers, acting like an **in-memory - Decouples your application from persistence frameworks - Promotes testability > Repository should not have methods like Update and Save -## A little note on Unit of Work +# Unit of Work Keeps track of changes and coordinates the writings and savings ## Implementation: https://youtu.be/rtXpYpZdOzM?t=703 diff --git a/02_ProjectOrientedSessions/Session02/Session02 Additional Info.md b/02_ProjectOrientedSessions/Session02/Session02 Additional Info.md new file mode 100644 index 0000000..518be24 --- /dev/null +++ b/02_ProjectOrientedSessions/Session02/Session02 Additional Info.md @@ -0,0 +1,62 @@ +## Cardinality +### Cardinality in Database Relationships + +Cardinality in databases refers to the number of relationships between records in two tables. It defines how many instances of one entity can be associated with instances of another entity. Cardinality is a crucial concept in database design because it ensures data integrity and optimizes query performance. + +--- + +### **Types of Cardinality** + +1. **One-to-One (1:1)** + + - Each record in Table A is related to exactly one record in Table B, and vice versa. + + - Example: A _person_ has one _passport_, and a _passport_ belongs to only one _person_. + + - Implementation: Typically enforced with a **unique foreign key**. + +2. **One-to-Many (1:M)** + + - A record in Table A can have multiple related records in Table B, but a record in Table B is linked to only one record in Table A. + + - Example: A _customer_ can place multiple _orders_, but each _order_ is placed by only one _customer_. + + - Implementation: A **foreign key** in Table B referring to the primary key in Table A. + +3. **Many-to-Many (M:M)** + + - Multiple records in Table A can relate to multiple records in Table B. + + - Example: _Students_ enroll in multiple _courses_, and each _course_ has multiple _students_. + + - Implementation: A **junction (bridge) table** with foreign keys referencing both tables. + + +--- + +### **Cardinality Constraints** + +Cardinality can be further specified using **minimum and maximum** constraints: + +- **(0,1): Optional One** → A record may or may not be related. + +- **(1,1): Mandatory One** → A record must always be related to exactly one record. + +- **(0,N): Optional Many** → A record may have many related records or none. + +- **(1,N): Mandatory Many** → A record must have at least one related record. + + +--- + +### **Practical Example** + +Consider a database with `Students` and `Courses`: + +- **One-to-Many:** A _teacher_ teaches multiple _courses_, but each _course_ has only one _teacher_. + +- **Many-to-Many:** _Students_ enroll in multiple _courses_, and _courses_ have multiple _students_. This is implemented using a **StudentCourses** junction table. + + +Would you like a more detailed example or SQL implementation? 🚀 + diff --git a/02_ProjectOrientedSessions/Session02/Session 02 Document.md b/02_ProjectOrientedSessions/Session02/Session02 Backend.md similarity index 84% rename from 02_ProjectOrientedSessions/Session02/Session 02 Document.md rename to 02_ProjectOrientedSessions/Session02/Session02 Backend.md index ae06d51..a6e7bf5 100644 --- a/02_ProjectOrientedSessions/Session02/Session 02 Document.md +++ b/02_ProjectOrientedSessions/Session02/Session02 Backend.md @@ -448,7 +448,7 @@ app.Run(); ``` Add-Migration InitialCreate ``` -- [ ] In case of scuccues: +- [ ] In case of succus: ``` Update-Database ``` @@ -456,67 +456,3 @@ Update-Database - [ ] Create a PR and merge the current branch with develop --- -# Additional Notes -## Cardinality -### Cardinality in Database Relationships - -Cardinality in databases refers to the number of relationships between records in two tables. It defines how many instances of one entity can be associated with instances of another entity. Cardinality is a crucial concept in database design because it ensures data integrity and optimizes query performance. - ---- - -### **Types of Cardinality** - -1. **One-to-One (1:1)** - - - Each record in Table A is related to exactly one record in Table B, and vice versa. - - - Example: A _person_ has one _passport_, and a _passport_ belongs to only one _person_. - - - Implementation: Typically enforced with a **unique foreign key**. - -2. **One-to-Many (1:M)** - - - A record in Table A can have multiple related records in Table B, but a record in Table B is linked to only one record in Table A. - - - Example: A _customer_ can place multiple _orders_, but each _order_ is placed by only one _customer_. - - - Implementation: A **foreign key** in Table B referring to the primary key in Table A. - -3. **Many-to-Many (M:M)** - - - Multiple records in Table A can relate to multiple records in Table B. - - - Example: _Students_ enroll in multiple _courses_, and each _course_ has multiple _students_. - - - Implementation: A **junction (bridge) table** with foreign keys referencing both tables. - - ---- - -### **Cardinality Constraints** - -Cardinality can be further specified using **minimum and maximum** constraints: - -- **(0,1): Optional One** → A record may or may not be related. - -- **(1,1): Mandatory One** → A record must always be related to exactly one record. - -- **(0,N): Optional Many** → A record may have many related records or none. - -- **(1,N): Mandatory Many** → A record must have at least one related record. - - ---- - -### **Practical Example** - -Consider a database with `Students` and `Courses`: - -- **One-to-Many:** A _teacher_ teaches multiple _courses_, but each _course_ has only one _teacher_. - -- **Many-to-Many:** _Students_ enroll in multiple _courses_, and _courses_ have multiple _students_. This is implemented using a **StudentCourses** junction table. - - -Would you like a more detailed example or SQL implementation? 🚀 - -## \ No newline at end of file diff --git a/02_ProjectOrientedSessions/Session02-Fixes/Join Table.md b/02_ProjectOrientedSessions/Session02/Session02 Fixes.md similarity index 98% rename from 02_ProjectOrientedSessions/Session02-Fixes/Join Table.md rename to 02_ProjectOrientedSessions/Session02/Session02 Fixes.md index 1867d1d..2b601ee 100644 --- a/02_ProjectOrientedSessions/Session02-Fixes/Join Table.md +++ b/02_ProjectOrientedSessions/Session02/Session02 Fixes.md @@ -1,5 +1,5 @@ -Great question! The **accountRole** table is a **many-to-many join table** with only two foreign keys (`AccountId`, `RoleId`) and no extra fields. Since it's just linking **Accounts** and **Roles**, you might not need a repository for it. Let's explore the best approach. + The **accountRole** table is a **many-to-many join table** with only two foreign keys (`AccountId`, `RoleId`) and no extra fields. Since it's just linking **Accounts** and **Roles**, you might not need a repository for it. Let's explore the best approach. --- diff --git a/02_ProjectOrientedSessions/Session03/Session 03 Document.md b/02_ProjectOrientedSessions/Session03/Session03 Backend.md similarity index 51% rename from 02_ProjectOrientedSessions/Session03/Session 03 Document.md rename to 02_ProjectOrientedSessions/Session03/Session03 Backend.md index 9590e70..511e8be 100644 --- a/02_ProjectOrientedSessions/Session03/Session 03 Document.md +++ b/02_ProjectOrientedSessions/Session03/Session03 Backend.md @@ -1,136 +1,3 @@ -# Introduction to Repository Pattern (Chat GPT): -The **Repository Pattern** in ASP.NET Core is a design pattern used to separate business logic from data access logic by providing an abstraction layer over database operations. This pattern improves maintainability, testability, and flexibility in applications by encapsulating database operations in dedicated repository classes. - ---- -## **Why Use the Repository Pattern?** - -### **Pros:** - -1. **Abstraction from ORM (Entity Framework Core)** - - Prevents direct dependency on EF Core, making it easier to swap out the data access layer in the future. - -2. **Better Code Organization** - - Separates concerns by keeping data logic in repositories and business logic in services/controllers. - -3. **Improved Testability** - - Makes it easier to mock repositories in unit tests. - -4. **Encapsulation of Queries** - - Common queries can be abstracted, reducing repetition. - -5. **Centralized Data Access Logic** - - Ensures a single location for handling CRUD operations. - - ---- - -## **Comparison: Repository Pattern vs. Direct DbSet Operations** - -| Feature | Using Repository Pattern | Using DbSet Directly in Controllers | -| -------------------------- | -------------------------------------- | -------------------------------------- | -| **Separation of Concerns** | ✅ Maintains separation | ❌ Business and data access logic mixed | -| **Testability** | ✅ Easy to mock and test | ❌ Harder to mock DbContext | -| **Code Reusability** | ✅ Common operations are encapsulated | ❌ Repetitive DbSet calls | -| **Flexibility** | ✅ Can switch database providers easily | ❌ Tightly coupled to EF Core | - ---- - -## **Implementation of the Repository Pattern** - -We will create: - -1. **IRepository** (Generic repository interface) - -2. **Repository** (Generic repository implementation) - -3. **Entity-specific repositories** (e.g., `ICustomerRepository` and `CustomerRepository`) - - -# Introduction to Unit of Work Pattern (Chat GPT): - -## **What is the Unit of Work Pattern?** - -The **Unit of Work (UoW)** pattern is a **centralized mechanism** to manage **database transactions** and ensure that multiple repository operations are treated as a single unit of execution. It acts as a wrapper around multiple repositories to **coordinate their changes and commit them in one go**. - ---- - -## **Advantages of Unit of Work** - -### **1. Single Transaction for Multiple Operations** - -- If you're performing **multiple database operations** across different repositories, **Unit of Work ensures atomicity**. -- If one operation fails, everything is **rolled back** (when using explicit transactions). - -### **2. Better Performance** - -- **Without UoW:** Every repository would call `SaveChangesAsync()` separately, causing multiple round trips to the database. -- **With UoW:** All changes are saved **at once**, reducing the number of database calls. -### **3. Maintains Consistency** -- When multiple repositories modify related entities, **UoW ensures that all changes are either committed or discarded together**. -### **4. Improves Testability** -- Unit of Work allows you to **mock database changes** and write unit tests efficiently without worrying about inconsistent data states. -### **5. Prevents Partial Updates** -- If multiple repositories handle different entities in the same operation, calling `SaveChangesAsync()` in individual repositories could lead to **partial updates** if one operation succeeds and another fails. - ---- - -## **Why Should `SaveChanges()` NOT Be in the Repository?** - -### **1. Each Repository Should Not Control Transactions** - -If each repository calls `SaveChangesAsync()`, **you lose control over transactions**. - -#### **Example Problem (Without UoW)** - -Imagine you have two repositories: `CustomerRepository` and `OrderRepository`. -If you try to **add a customer** and **add an order** separately, each calling `SaveChangesAsync()`: - -```csharp -var customer = new Customer { Name = "John Doe" }; -await _customerRepository.AddAsync(customer); -await _customerRepository.SaveChangesAsync(); // ❌ First database call - -var order = new Order { CustomerId = customer.Id, TotalAmount = 100 }; -await _orderRepository.AddAsync(order); -await _orderRepository.SaveChangesAsync(); // ❌ Second database call -``` - -**What happens if the second `SaveChangesAsync()` fails?** - -- The customer has already been saved, but the order is missing. -- **Your database is left in an inconsistent state!** - -### **2. Database Round Trips (Performance Issue)** - -If each repository calls `SaveChangesAsync()`, you end up with **multiple database calls** instead of batching them into a single transaction. - -```csharp -await _customerRepository.SaveChangesAsync(); // ❌ DB call -await _orderRepository.SaveChangesAsync(); // ❌ Another DB call -``` - -Using **Unit of Work**, all changes can be saved in one go: - -```csharp -await _unitOfWork.SaveChangesAsync(); // ✅ One database call -``` - -This **reduces network latency** and improves **database performance**. - -### **3. Promotes Separation of Concerns** - -- **Repositories should focus on CRUD operations** (data retrieval and manipulation). -- **Unit of Work should manage transactions**. -- This makes the code **cleaner and easier to maintain**. ---- - -## **Key Takeaways** - -✔ **Unit of Work ensures all database operations are part of a single transaction**. -✔ **Repositories should NOT call `SaveChangesAsync()` to avoid multiple transactions**. -✔ **EF Core tracks changes, so calling `SaveChangesAsync()` once is enough**. -✔ **Using UoW improves performance, consistency, and maintainability**. ---- # 1. Implementing Repository Pattern ## Branching diff --git a/02_ProjectOrientedSessions/Session03/Session03 Preparation.md b/02_ProjectOrientedSessions/Session03/Session03 Preparation.md new file mode 100644 index 0000000..bbc0838 --- /dev/null +++ b/02_ProjectOrientedSessions/Session03/Session03 Preparation.md @@ -0,0 +1,131 @@ +# Introduction to Repository Pattern (Chat GPT): +The **Repository Pattern** in ASP.NET Core is a design pattern used to separate business logic from data access logic by providing an abstraction layer over database operations. This pattern improves maintainability, testability, and flexibility in applications by encapsulating database operations in dedicated repository classes. + +--- +## **Why Use the Repository Pattern?** + +### **Pros:** + +1. **Abstraction from ORM (Entity Framework Core)** + - Prevents direct dependency on EF Core, making it easier to swap out the data access layer in the future. + +2. **Better Code Organization** + - Separates concerns by keeping data logic in repositories and business logic in services/controllers. + +3. **Improved Testability** + - Makes it easier to mock repositories in unit tests. + +4. **Encapsulation of Queries** + - Common queries can be abstracted, reducing repetition. + +5. **Centralized Data Access Logic** + - Ensures a single location for handling CRUD operations. + + +--- + +## **Comparison: Repository Pattern vs. Direct DbSet Operations** + +| Feature | Using Repository Pattern | Using DbSet Directly in Controllers | +| -------------------------- | -------------------------------------- | -------------------------------------- | +| **Separation of Concerns** | ✅ Maintains separation | ❌ Business and data access logic mixed | +| **Testability** | ✅ Easy to mock and test | ❌ Harder to mock DbContext | +| **Code Reusability** | ✅ Common operations are encapsulated | ❌ Repetitive DbSet calls | +| **Flexibility** | ✅ Can switch database providers easily | ❌ Tightly coupled to EF Core | + +--- + +## **Implementation of the Repository Pattern** + +We will create: + +1. **IRepository** (Generic repository interface) +2. **Repository** (Generic repository implementation) +3. **Entity-specific repositories** (e.g., `ICustomerRepository` and `CustomerRepository`) + + +# Introduction to Unit of Work Pattern (Chat GPT): + +## **What is the Unit of Work Pattern?** + +The **Unit of Work (UoW)** pattern is a **centralized mechanism** to manage **database transactions** and ensure that multiple repository operations are treated as a single unit of execution. It acts as a wrapper around multiple repositories to **coordinate their changes and commit them in one go**. + +--- + +## **Advantages of Unit of Work** + +### **1. Single Transaction for Multiple Operations** + +- If you're performing **multiple database operations** across different repositories, **Unit of Work ensures atomicity**. +- If one operation fails, everything is **rolled back** (when using explicit transactions). + +### **2. Better Performance** + +- **Without UoW:** Every repository would call `SaveChangesAsync()` separately, causing multiple round trips to the database. +- **With UoW:** All changes are saved **at once**, reducing the number of database calls. +### **3. Maintains Consistency** +- When multiple repositories modify related entities, **UoW ensures that all changes are either committed or discarded together**. +### **4. Improves Testability** +- Unit of Work allows you to **mock database changes** and write unit tests efficiently without worrying about inconsistent data states. +### **5. Prevents Partial Updates** +- If multiple repositories handle different entities in the same operation, calling `SaveChangesAsync()` in individual repositories could lead to **partial updates** if one operation succeeds and another fails. + +--- + +## **Why Should `SaveChanges()` NOT Be in the Repository?** + +### **1. Each Repository Should Not Control Transactions** + +If each repository calls `SaveChangesAsync()`, **you lose control over transactions**. + +#### **Example Problem (Without UoW)** + +Imagine you have two repositories: `CustomerRepository` and `OrderRepository`. +If you try to **add a customer** and **add an order** separately, each calling `SaveChangesAsync()`: + +```csharp +var customer = new Customer { Name = "John Doe" }; +await _customerRepository.AddAsync(customer); +await _customerRepository.SaveChangesAsync(); // ❌ First database call + +var order = new Order { CustomerId = customer.Id, TotalAmount = 100 }; +await _orderRepository.AddAsync(order); +await _orderRepository.SaveChangesAsync(); // ❌ Second database call +``` + +**What happens if the second `SaveChangesAsync()` fails?** + +- The customer has already been saved, but the order is missing. +- **Your database is left in an inconsistent state!** + +### **2. Database Round Trips (Performance Issue)** + +If each repository calls `SaveChangesAsync()`, you end up with **multiple database calls** instead of batching them into a single transaction. + +```csharp +await _customerRepository.SaveChangesAsync(); // ❌ DB call +await _orderRepository.SaveChangesAsync(); // ❌ Another DB call +``` + +Using **Unit of Work**, all changes can be saved in one go: + +```csharp +await _unitOfWork.SaveChangesAsync(); // ✅ One database call +``` + +This **reduces network latency** and improves **database performance**. + +### **3. Promotes Separation of Concerns** + +- **Repositories should focus on CRUD operations** (data retrieval and manipulation). +- **Unit of Work should manage transactions**. +- This makes the code **cleaner and easier to maintain**. +--- + +## **Key Takeaways** + +✔ **Unit of Work ensures all database operations are part of a single transaction**. +✔ **Repositories should NOT call `SaveChangesAsync()` to avoid multiple transactions**. +✔ **EF Core tracks changes, so calling `SaveChangesAsync()` once is enough**. +✔ **Using UoW improves performance, consistency, and maintainability**. +-- \ No newline at end of file diff --git a/02_ProjectOrientedSessions/Session04/Session04 Additional Info.md b/02_ProjectOrientedSessions/Session04/Session04 Additional Info.md new file mode 100644 index 0000000..651c561 --- /dev/null +++ b/02_ProjectOrientedSessions/Session04/Session04 Additional Info.md @@ -0,0 +1,320 @@ +### 1. **Should I have an `IEntityService` and then `EntityService` for each of my entities?** + +Not necessarily **for _every_** entity — only if it **makes sense**. + +- The Application Layer should expose **use cases** — not just CRUD logic for each entity. + +- If an entity has business logic or interactions that need orchestration (e.g., validations, aggregations, calling repositories, etc.), then **yes**, create a service. + +- Otherwise, for basic operations, **directly using a repository (via a unit of work or interface)** from the use case handler might be fine. +### 2. **Is it OK to have services not related to a specific entity?** + +Absolutely, **yes**. In fact, that’s expected in a Clean Architecture setup. + +Examples: + +- A `ReportGenerationService` that combines bookings, customers, and payments. + +- A `TokenService` for authentication tokens. + +- A `CurrencyConversionService` that hits an external API. + +- A `NotificationService` that sends emails or SMS. + + +👉 As long as these services **live in the Application Layer** and follow **dependency inversion** (i.e., they depend only on interfaces, not implementations), you’re doing great. + +### 3. **Is it necessary to have an interface for each service?** + + + +### 🔹 **What’s the Difference Between Services and Repositories?** + +| Aspect | **Service** | **Repository** | +| ------------------ | ---------------------------------------------------------------------- | --------------------------------------------------------------- | +| **Layer** | Application Layer | Domain Layer (interface), Infrastructure Layer (implementation) | +| **Responsibility** | **Orchestrates business logic** / use cases | **Data access abstraction** | +| **Focus** | Coordinates multiple domain/repo operations, validation, business flow | Fetching/storing data for a specific entity | +| **Example** | `PlaceOrderService`, `ReportService` | `ICustomerRepository`, `IOrderRepository` | + +### What does `init` mean? + +`init` is an **access modifier for properties** that allows you to **set a property only during object initialization**, **but not after**. + + +## Should I use `class` or `record` for DTOs in Clean Architecture? + +### 🔵 Short answer: + +> **Use `record` for DTOs when possible** — it's clean, immutable by default, and semantically perfect for data transfer. + +--- + +### 🔍 Why `record` is a great fit for DTOs + +| Feature | `record` | `class` | +| ----------------------- | ----------------- | ---------------------------- | +| Immutable by default | ✅ (with `init`) | ❌ (need manual setup) | +| Value-based equality | ✅ | ❌ (ref-based by default) | +| Concise syntax | ✅ | ❌ (more boilerplate) | +| Use for data containers | ✅ (perfect fit) | ✅ (but more verbose) | +| Custom behavior/logic | ❌ (less suitable) | ✅ (better for rich behavior) | +### But when should you prefer `class`? + +Use `class` if your DTO or model: + +- Needs to be **mutable** after creation + +- Has to **interact with legacy APIs/libraries** + +- Needs **inheritance or polymorphism** (not well supported in `record`) + +- Has **rich behavior** (logic, methods, validation, etc.) + + +> For example, in the Domain Layer (Entities, ValueObjects), you'll usually stick to **`class`** — because that's where behavior lives. + +## RESTful APIs: +https://aws.amazon.com/what-is/restful-api/#:~:text=RESTful%20API%20is%20an%20interface,applications%20to%20perform%20various%20tasks. + +## What Conditions Make an API RESTful? + +### Key Principles of REST: + +1. **Statelessness**: + + - Each API call must contain all the information the server needs to fulfill the request (no session state). Each request is independent. + +2. **Resource Identification**: + + - Resources (e.g., customers, orders) should be identified using URIs. Use nouns in URIs, not verbs. + +3. **HTTP Methods**: + + - Use standard HTTP methods to represent actions: + + - **GET**: Retrieve a resource. + + - **POST**: Create a new resource. + + - **PUT**: Update a resource entirely. + + - **PATCH**: Update a resource partially. + + - **DELETE**: Remove a resource. + +4. **Use of Standard Status Codes**: + + - Return appropriate HTTP status codes (e.g., `200 OK`, `201 Created`, `404 Not Found`, `500 Internal Server Error`). + +5. **HATEOAS**: + + - (Hypermedia as the Engine of Application State) - Provide links to related resources within the responses. + + +### Multiple GET Methods in One Controller: + +- **Yes, you can have multiple GET methods in one controller**. The key is to differentiate them based on routes and parameters. + +- For example: + + +```c# +[ApiController] +[Route("api/[controller]")] +public class CustomerController : ControllerBase { + + [HttpGet("{id}")] + public IActionResult GetCustomerById(int id) { /*...*/ } + + [HttpGet] + public IActionResult GetAllCustomers() { /*...*/ } + + [HttpGet("{id}/orders")] + public IActionResult GetCustomerOrders(int id) { /*...*/ } +} +``` + + +- **Routing**: ASP.NET Core uses route templates to differentiate these actions. The combination of route parameters, query strings, and action names can help separate the GET requests. + + +## List-like stuff in `C#` +Absolutely, let’s go over the main “list-like” data types in C#. They all serve similar purposes—holding multiple items—but differ in functionality, performance, and use cases. Here’s a detailed breakdown: + +🔷 1. `IEnumerable` + +- Namespace: System.Collections.Generic + +- Most basic "list-like" abstraction. + +- Read-only (forward-only iteration). + +- You can use foreach on it. + +- Doesn’t support indexing (no .Count, no [i]). + +- Often used as the return type to expose a stream of data without giving full collection control. + + +Example: + +```csharp +IEnumerable numbers = GetNumbers(); // Lazy-loaded maybe +foreach (var num in numbers) + Console.WriteLine(num); +``` + +💡 Ideal when: + +- You want to return a sequence without exposing modification. + +- You’re using LINQ chains. + +- You’re returning data from a database query. + + +--- + +🔷 2. ICollection + +- Extends IEnumerable. + +- Adds Count and Add/Remove/Clear methods. + +- Still abstract—List and HashSet implement it. + + +💡 Useful when: + +- You want to expose a collection that can be modified (e.g. Add or Remove). + +- You care about the Count. + + +--- + +🔷 3. IList + +- Extends ICollection and IEnumerable. + +- Adds index access: list[0] etc. + +- Think of it like a mutable array with dynamic size. + + +💡 Use when: + +- You want ordered collection with indexing. + +- You need to insert, remove, or replace items at specific positions. + + +--- + +🔷 4. List + +- A concrete class (not interface). + +- Implements IList, ICollection, IEnumerable. + +- Backed by an array (auto-resizes). + +- Fast read and write. + +- Supports Add, Remove, Insert, IndexOf, etc. + + +Example: + +```csharp +var list = new List(); +list.Add("One"); +list.Add("Two"); +var second = list[1]; // "Two" +``` + +💡 Go-to general purpose collection. + +--- + +🔷 5. IReadOnlyCollection & IReadOnlyList + +- IReadOnlyCollection: Just Count and IEnumerable. + +- IReadOnlyList: Adds indexing without modification. + +- Used to expose lists safely (read-only). + + +💡 Used when: + +- You want to return a list, but prevent any changes. + + +--- + +🔷 6. Array (T[]) + +- Fixed-size. + +- Fastest for indexing. + +- Cannot change size. + +- Implements IList (via Array). + + +Example: + +```csharp +int[] numbers = new int[5]; +numbers[0] = 42; +``` + +💡 Great for performance-sensitive or fixed-size data. + +--- + +🔷 7. ObservableCollection + +- For WPF/Blazor/WinForms data-binding. + +- Notifies UI when items are added/removed. + +- Implements IList. + + +💡 Use in UI apps when the view needs to react to collection changes. + +--- + +🔷 8. HashSet + +- Unordered, no duplicates. + +- Implements ICollection, not IList. + +- No index access. + + +💡 Best for fast membership checking (contains x). + +--- + +🔷 Summary Table + +|Type|Indexing|Modifiable|Ordered|Duplicates|Use Case| +|---|---|---|---|---|---| +|IEnumerable|❌|❌|✔️|✔️|Basic read-only stream or LINQ chaining| +|ICollection|❌|✔️|✔️|✔️|Expose modifiable group of items| +|IList|✔️|✔️|✔️|✔️|Full-featured list abstraction| +|List|✔️|✔️|✔️|✔️|Standard go-to collection| +|IReadOnlyList|✔️|❌|✔️|✔️|Return data safely from service or repo| +|Array (T[])|✔️|✔️|✔️|✔️|Fixed-size, performant indexing| +|ObservableCollection|✔️|✔️|✔️|✔️|UI binding for collections| +|HashSet|❌|✔️|❌|❌|Fast lookup, uniqueness enforcement| + +— + +If you tell me the scenario (e.g. search results, modifying a cart, populating a drop-down), I can recommend the best type for it. Want that? diff --git a/02_ProjectOrientedSessions/Session04/Session04.md b/02_ProjectOrientedSessions/Session04/Session04 Backend.md similarity index 52% rename from 02_ProjectOrientedSessions/Session04/Session04.md rename to 02_ProjectOrientedSessions/Session04/Session04 Backend.md index a5ac8ab..f5e5bcb 100644 --- a/02_ProjectOrientedSessions/Session04/Session04.md +++ b/02_ProjectOrientedSessions/Session04/Session04 Backend.md @@ -220,7 +220,7 @@ public enum ResultStatus You can read more about enums: [W3Schools](https://www.w3schools.com/cs/cs_enums.php) -# IService & Service +# `IService` & Service Now, use `I[Entity]Repositry` and `IUnitOfWork` in services to implement business logic @@ -361,325 +361,3 @@ You are provided with a SQL script, that adds some sample data into the followin # Merge - [ ] Create a PR and merge the current branch with develop - -# Additional Info -### 1. **Should I have an `IEntityService` and then `EntityService` for each of my entities?** - -Not necessarily **for _every_** entity — only if it **makes sense**. - -- The Application Layer should expose **use cases** — not just CRUD logic for each entity. - -- If an entity has business logic or interactions that need orchestration (e.g., validations, aggregations, calling repositories, etc.), then **yes**, create a service. - -- Otherwise, for basic operations, **directly using a repository (via a unit of work or interface)** from the use case handler might be fine. -### 2. **Is it OK to have services not related to a specific entity?** - -Absolutely, **yes**. In fact, that’s expected in a Clean Architecture setup. - -Examples: - -- A `ReportGenerationService` that combines bookings, customers, and payments. - -- A `TokenService` for authentication tokens. - -- A `CurrencyConversionService` that hits an external API. - -- A `NotificationService` that sends emails or SMS. - - -👉 As long as these services **live in the Application Layer** and follow **dependency inversion** (i.e., they depend only on interfaces, not implementations), you’re doing great. - -### 3. **Is it necessary to have an interface for each service?** - - - -### 🔹 **What’s the Difference Between Services and Repositories?** - -| Aspect | **Service** | **Repository** | -| ------------------ | ---------------------------------------------------------------------- | --------------------------------------------------------------- | -| **Layer** | Application Layer | Domain Layer (interface), Infrastructure Layer (implementation) | -| **Responsibility** | **Orchestrates business logic** / use cases | **Data access abstraction** | -| **Focus** | Coordinates multiple domain/repo operations, validation, business flow | Fetching/storing data for a specific entity | -| **Example** | `PlaceOrderService`, `ReportService` | `ICustomerRepository`, `IOrderRepository` | - -### What does `init` mean? - -`init` is an **access modifier for properties** that allows you to **set a property only during object initialization**, **but not after**. - - -## Should I use `class` or `record` for DTOs in Clean Architecture? - -### 🔵 Short answer: - -> **Use `record` for DTOs when possible** — it's clean, immutable by default, and semantically perfect for data transfer. - ---- - -### 🔍 Why `record` is a great fit for DTOs - -| Feature | `record` | `class` | -| ----------------------- | ----------------- | ---------------------------- | -| Immutable by default | ✅ (with `init`) | ❌ (need manual setup) | -| Value-based equality | ✅ | ❌ (ref-based by default) | -| Concise syntax | ✅ | ❌ (more boilerplate) | -| Use for data containers | ✅ (perfect fit) | ✅ (but more verbose) | -| Custom behavior/logic | ❌ (less suitable) | ✅ (better for rich behavior) | -### But when should you prefer `class`? - -Use `class` if your DTO or model: - -- Needs to be **mutable** after creation - -- Has to **interact with legacy APIs/libraries** - -- Needs **inheritance or polymorphism** (not well supported in `record`) - -- Has **rich behavior** (logic, methods, validation, etc.) - - -> For example, in the Domain Layer (Entities, ValueObjects), you'll usually stick to **`class`** — because that's where behavior lives. - -## RESTful APIs: -https://aws.amazon.com/what-is/restful-api/#:~:text=RESTful%20API%20is%20an%20interface,applications%20to%20perform%20various%20tasks. - -## What Conditions Make an API RESTful? - -### Key Principles of REST: - -1. **Statelessness**: - - - Each API call must contain all the information the server needs to fulfill the request (no session state). Each request is independent. - -2. **Resource Identification**: - - - Resources (e.g., customers, orders) should be identified using URIs. Use nouns in URIs, not verbs. - -3. **HTTP Methods**: - - - Use standard HTTP methods to represent actions: - - - **GET**: Retrieve a resource. - - - **POST**: Create a new resource. - - - **PUT**: Update a resource entirely. - - - **PATCH**: Update a resource partially. - - - **DELETE**: Remove a resource. - -4. **Use of Standard Status Codes**: - - - Return appropriate HTTP status codes (e.g., `200 OK`, `201 Created`, `404 Not Found`, `500 Internal Server Error`). - -5. **HATEOAS**: - - - (Hypermedia as the Engine of Application State) - Provide links to related resources within the responses. - - -### Multiple GET Methods in One Controller: - -- **Yes, you can have multiple GET methods in one controller**. The key is to differentiate them based on routes and parameters. - -- For example: - - -```c# -[ApiController] -[Route("api/[controller]")] -public class CustomerController : ControllerBase { - - [HttpGet("{id}")] - public IActionResult GetCustomerById(int id) { /*...*/ } - - [HttpGet] - public IActionResult GetAllCustomers() { /*...*/ } - - [HttpGet("{id}/orders")] - public IActionResult GetCustomerOrders(int id) { /*...*/ } -} -``` - - -- **Routing**: ASP.NET Core uses route templates to differentiate these actions. The combination of route parameters, query strings, and action names can help separate the GET requests. - - -## List-like stuff in `C#` -Absolutely, let’s go over the main “list-like” data types in C#. They all serve similar purposes—holding multiple items—but differ in functionality, performance, and use cases. Here’s a detailed breakdown: - -🔷 1. `IEnumerable` - -- Namespace: System.Collections.Generic - -- Most basic "list-like" abstraction. - -- Read-only (forward-only iteration). - -- You can use foreach on it. - -- Doesn’t support indexing (no .Count, no [i]). - -- Often used as the return type to expose a stream of data without giving full collection control. - - -Example: - -```csharp -IEnumerable numbers = GetNumbers(); // Lazy-loaded maybe -foreach (var num in numbers) - Console.WriteLine(num); -``` - -💡 Ideal when: - -- You want to return a sequence without exposing modification. - -- You’re using LINQ chains. - -- You’re returning data from a database query. - - ---- - -🔷 2. ICollection - -- Extends IEnumerable. - -- Adds Count and Add/Remove/Clear methods. - -- Still abstract—List and HashSet implement it. - - -💡 Useful when: - -- You want to expose a collection that can be modified (e.g. Add or Remove). - -- You care about the Count. - - ---- - -🔷 3. IList - -- Extends ICollection and IEnumerable. - -- Adds index access: list[0] etc. - -- Think of it like a mutable array with dynamic size. - - -💡 Use when: - -- You want ordered collection with indexing. - -- You need to insert, remove, or replace items at specific positions. - - ---- - -🔷 4. List - -- A concrete class (not interface). - -- Implements IList, ICollection, IEnumerable. - -- Backed by an array (auto-resizes). - -- Fast read and write. - -- Supports Add, Remove, Insert, IndexOf, etc. - - -Example: - -```csharp -var list = new List(); -list.Add("One"); -list.Add("Two"); -var second = list[1]; // "Two" -``` - -💡 Go-to general purpose collection. - ---- - -🔷 5. IReadOnlyCollection & IReadOnlyList - -- IReadOnlyCollection: Just Count and IEnumerable. - -- IReadOnlyList: Adds indexing without modification. - -- Used to expose lists safely (read-only). - - -💡 Used when: - -- You want to return a list, but prevent any changes. - - ---- - -🔷 6. Array (T[]) - -- Fixed-size. - -- Fastest for indexing. - -- Cannot change size. - -- Implements IList (via Array). - - -Example: - -```csharp -int[] numbers = new int[5]; -numbers[0] = 42; -``` - -💡 Great for performance-sensitive or fixed-size data. - ---- - -🔷 7. ObservableCollection - -- For WPF/Blazor/WinForms data-binding. - -- Notifies UI when items are added/removed. - -- Implements IList. - - -💡 Use in UI apps when the view needs to react to collection changes. - ---- - -🔷 8. HashSet - -- Unordered, no duplicates. - -- Implements ICollection, not IList. - -- No index access. - - -💡 Best for fast membership checking (contains x). - ---- - -🔷 Summary Table - -|Type|Indexing|Modifiable|Ordered|Duplicates|Use Case| -|---|---|---|---|---|---| -|IEnumerable|❌|❌|✔️|✔️|Basic read-only stream or LINQ chaining| -|ICollection|❌|✔️|✔️|✔️|Expose modifiable group of items| -|IList|✔️|✔️|✔️|✔️|Full-featured list abstraction| -|List|✔️|✔️|✔️|✔️|Standard go-to collection| -|IReadOnlyList|✔️|❌|✔️|✔️|Return data safely from service or repo| -|Array (T[])|✔️|✔️|✔️|✔️|Fixed-size, performant indexing| -|ObservableCollection|✔️|✔️|✔️|✔️|UI binding for collections| -|HashSet|❌|✔️|❌|❌|Fast lookup, uniqueness enforcement| - -— - -If you tell me the scenario (e.g. search results, modifying a cart, populating a drop-down), I can recommend the best type for it. Want that? diff --git a/02_ProjectOrientedSessions/Session05/React/Mosh React.md b/02_ProjectOrientedSessions/Session05/React/Mosh React.md new file mode 100644 index 0000000..12a60f2 --- /dev/null +++ b/02_ProjectOrientedSessions/Session05/React/Mosh React.md @@ -0,0 +1 @@ +- [ ] Watch https://www.youtube.com/watch?v=SqcY0GlETPk&ab_channel=ProgrammingwithMosh \ No newline at end of file diff --git a/React/Resources.md b/02_ProjectOrientedSessions/Session05/React/Resources.md similarity index 100% rename from React/Resources.md rename to 02_ProjectOrientedSessions/Session05/React/Resources.md diff --git a/React/Mosh React.md b/02_ProjectOrientedSessions/Session05/Session05 Additional Info.md similarity index 100% rename from React/Mosh React.md rename to 02_ProjectOrientedSessions/Session05/Session05 Additional Info.md diff --git a/02_ProjectOrientedSessions/Session05/Session05 Backend.md b/02_ProjectOrientedSessions/Session05/Session05 Backend.md new file mode 100644 index 0000000..1066c8b --- /dev/null +++ b/02_ProjectOrientedSessions/Session05/Session05 Backend.md @@ -0,0 +1,19 @@ +# CORS (Backend Repository) +- [ ] open `program.cs` and add the following lines + +```c# +builder.Services.AddCors(options => +{ + options.AddPolicy("Frontend", policy => + { + policy.WithOrigins("http://localhost:5173") + .AllowAnyHeader() + .AllowAnyMethod(); + }); +}); + +... + +app.UseCors("Frontend"); +``` + diff --git a/02_ProjectOrientedSessions/Session05/Session05.md b/02_ProjectOrientedSessions/Session05/Session05 Frontend.md similarity index 96% rename from 02_ProjectOrientedSessions/Session05/Session05.md rename to 02_ProjectOrientedSessions/Session05/Session05 Frontend.md index 8cc07d1..63446a9 100644 --- a/02_ProjectOrientedSessions/Session05/Session05.md +++ b/02_ProjectOrientedSessions/Session05/Session05 Frontend.md @@ -2,25 +2,6 @@ # Preparation - [ ] Watch https://www.youtube.com/watch?v=SqcY0GlETPk&ab_channel=ProgrammingwithMosh -# CORS (Backend Repository) -- [ ] open `program.cs` and add the following lines - -```c# -builder.Services.AddCors(options => -{ - options.AddPolicy("Frontend", policy => - { - policy.WithOrigins("http://localhost:5173") - .AllowAnyHeader() - .AllowAnyMethod(); - }); -}); - -... - -app.UseCors("Frontend"); -``` - # Important Note Before Starting @@ -340,26 +321,18 @@ You're using `React.FC`. - `React.FC` (or `React.FunctionComponent`) is a **TypeScript type** that you can use to type your functional React components. - It **tells TypeScript** that: - - This component is a function - - It **receives props** (in your case, `Props`) - - It **returns JSX** (it returns something React can render) - --- ### Why use it? Here’s what you get when you use `React.FC`: - 1. ✅ **Prop typing** — You get auto-complete and error checking for props. - 2. ✅ **Children** are automatically included. (More on this below.) - 3. ✅ **Cleaner code** because TypeScript understands the shape of the component. - --- @@ -370,7 +343,6 @@ You could just write: ```tsx const TransportationCard = ({ transportation }: Props) => { ... } ``` - and it would work! But you lose some "extra typing safety" like automatic `children` typing. @@ -419,9 +391,6 @@ Because `children` is **always** part of a `React.FC`. --- -Would you like me to also show a real quick **example side-by-side** (with and without `React.FC`) so you can see the difference even more clearly? 🚀 -(It's super fast but very helpful!) - ## `CityDropdown` Component: ### 1. **State Variables** @@ -432,7 +401,6 @@ const [selectedCity, setSelectedCity] = useState(); ``` - `cities`: holds the list of cities retrieved from the backend (starts empty `[]`). - - `selectedCity`: holds the currently selected city’s ID (`number`) or `undefined` if nothing is selected yet. @@ -450,11 +418,8 @@ useEffect(() => { - When the component **mounts** (`[]` dependency array = run once), it calls `agent.Cities.list()`. - `agent.Cities.list()` presumably returns a promise that resolves to an array of `City` objects. - - On success → `setCities` updates the `cities` state. - - On failure → logs an error to the console. - --- @@ -482,9 +447,6 @@ useEffect(() => { - `key` and `value` are the city's `id`. - Displayed text is the city's `title`. ---- -You're very welcome! Let's break it down even more clearly: - --- ### What is `useEffect`? @@ -493,7 +455,6 @@ You're very welcome! Let's break it down even more clearly: It **tells React to run some code after the component renders**. Think of it like: - - _"Hey React, when this component shows up on the screen, please also run this function!"_ @@ -539,18 +500,13 @@ Same with `selectedCity`: **Simple analogy:** Imagine your component is a whiteboard. - - `useState` gives you a small _erasable box_ on the board. - - You can write something there (`cities`, `selectedCity`). - - If you want to change what’s written, you use the special pen `setCities` or `setSelectedCity`, **not your finger** (so React knows it changed and redraws the screen if needed). --- - ## `TransportationCard` Component - ### 1. **The Component Function** ```tsx @@ -564,7 +520,6 @@ const TransportationCard: React.FC = ({ transportation }) => { --- ### 2. **Inside the JSX** - #### 2.1 Left Side — Price and Button ```tsx diff --git a/02_ProjectOrientedSessions/Session06/Session06.md b/02_ProjectOrientedSessions/Session06/Session06 Frontend.md similarity index 99% rename from 02_ProjectOrientedSessions/Session06/Session06.md rename to 02_ProjectOrientedSessions/Session06/Session06 Frontend.md index 2891bb6..e99e80f 100644 --- a/02_ProjectOrientedSessions/Session06/Session06.md +++ b/02_ProjectOrientedSessions/Session06/Session06 Frontend.md @@ -24,8 +24,6 @@ link to project: # Modifying Project From Single Component to Routed Pages - - Originally, your transportation search logic and UI may have all been inside one component — which quickly becomes messy and hard to manage as your app grows. Now we’ve **split the logic into two proper pages**: diff --git a/02_ProjectOrientedSessions/Session07/Session07 Additional Info.md b/02_ProjectOrientedSessions/Session07/Session07 Additional Info.md index 384dee3..b16cc9a 100644 --- a/02_ProjectOrientedSessions/Session07/Session07 Additional Info.md +++ b/02_ProjectOrientedSessions/Session07/Session07 Additional Info.md @@ -777,9 +777,9 @@ console.log(roles); // ["Admin", "Editor", "User"] ### Summary -|Step|How it works| -|---|---| -|JWT creation|Multiple `"role"` claims added to token| -|Backend authorization|Validates token and checks if user has required roles| -|Frontend decoding|Extracts `role` claim(s) as array of strings| -|Frontend UI control|Shows or hides content based on roles| +| Step | How it works | +| --------------------- | ----------------------------------------------------- | +| JWT creation | Multiple `"role"` claims added to token | +| Backend authorization | Validates token and checks if user has required roles | +| Frontend decoding | Extracts `role` claim(s) as array of strings | +| Frontend UI control | Shows or hides content based on roles | diff --git a/02_ProjectOrientedSessions/Session07/Session07 Backend.md b/02_ProjectOrientedSessions/Session07/Session07 Backend.md index b2643eb..92094e0 100644 --- a/02_ProjectOrientedSessions/Session07/Session07 Backend.md +++ b/02_ProjectOrientedSessions/Session07/Session07 Backend.md @@ -1,7 +1,7 @@ # Add a field in Database - [ ] Add `User` field in `Roles` table using SSMS or Seed data in DbContext file -- [ ] Make sure the property `PersonId` is nullable in `Account`, so you can add fields related to "Person" later after registeration +- [ ] Make sure the property `PersonId` is nullable in `Account`, so you can add fields related to "Person" later after registration # Branching - [ ] Create the feature/authentication branch based on develop diff --git a/02_ProjectOrientedSessions/Session08/New Roadmap.md b/02_ProjectOrientedSessions/Session08/New Roadmap.md deleted file mode 100644 index be18433..0000000 --- a/02_ProjectOrientedSessions/Session08/New Roadmap.md +++ /dev/null @@ -1,58 +0,0 @@ - -## Roadmap - -### Setup - -Estimated Time: - days -#### Backend - -- [ ] A -#### Frontend -- [ ] A - - - - -### Profile Page - -#### Creating BankDetailTable -#### ADd data into ticket status -Add phone number in person -person table- make id not unique - add creatorId - -#### -#### Tabs Panel like that (FULL) -#### Account Detail Tab (FULL) -#### My Travels Tab (FULL) -#### List of Travelers Tab (FULL) -#### My Favorites Tab (LATER) -#### Support Tab (LATER) -#### Transactions Tab (FULL) - Add balance to table - inc/dec balance - - -### Buying Tickets -#### Transportation Search Result 3 links -#### Showing seat status -#### The Select Ticket Page - Three different kinds, for bus, train, airplane -##### The header to show details and total price -##### The part for selecting seats (only for bus) -##### the list of people below it - - -### README and documentation - -## Optional Enhancements - -- [ ] Generic – You can use general types to avoid repetition and make code flexible, esp. in API - -- [ ] Responsive UI – Make sure the interface adjusts nicely - -- [ ] Theme – Support light/dark or customizable appearance - -- [ ] Server Log – Keep track of what happens on the server - -- [ ] Index in database – Improve how fast things are found in the database - -- [ ] Optimizing Multithreading – Make background work smoother and faster - -- [ ] Repository Pattern – Organize how data is handled and accessed \ No newline at end of file diff --git a/02_ProjectOrientedSessions/Session09/Database Transactions.md b/02_ProjectOrientedSessions/Session09/Database Transactions.md new file mode 100644 index 0000000..b30efc5 --- /dev/null +++ b/02_ProjectOrientedSessions/Session09/Database Transactions.md @@ -0,0 +1,766 @@ +To **safely handle concurrency** in your `CreateTicketOrderAsync` method — particularly for **seat reservation** on the same `Transportation` — you need to **prevent race conditions** where two users might reserve the same seat or oversell capacity. + +This is a **classic critical section problem**, and you can solve it using **application-level locking**, **database-level locking**, or both. + +--- + +## ✅ Recommended: **Database-level concurrency control + optional distributed lock** + +### 👇 Here’s what you should do: + +--- + +## ✅ 1. Use **pessimistic concurrency** (row-level locking) on the `Transportation` row + +### Why? + +You need to **lock the transportation row** to prevent multiple reservations from modifying the related seats/capacity **at the same time**. + +### How? + +Use EF Core's **raw SQL or transaction-scoped SELECT ... FOR UPDATE** (which translates to SQL row locks): + +```csharp +using var transaction = await _context.Database.BeginTransactionAsync(IsolationLevel.Serializable); + +var transportation = await _context.Transportations + .FromSqlRaw("SELECT * FROM Transportations WITH (UPDLOCK, ROWLOCK) WHERE Id = {0}", dto.TransportationId) + .FirstOrDefaultAsync(); +``` + +- `UPDLOCK`: prevents others from reading for update + +- `ROWLOCK`: locks only the specific row + + +> If using PostgreSQL or MySQL, you’d use `FOR UPDATE` instead. + +--- + +## ✅ 2. Alternatively, use **distributed locking** if you have multiple app instances + +Use something like: + +- **Redis distributed lock** + +- **SQL application locks** (`sp_getapplock`) + +- **SemaphoreSlim static lock** (only for single-instance apps — not safe in web farms) + + +### Example using `sp_getapplock` (SQL Server): + +```sql +EXEC sp_getapplock @Resource = 'lock_transportation_123', @LockMode = 'Exclusive', @LockTimeout = 10000; +``` + +EF version: + +```csharp +await _dbContext.Database.ExecuteSqlRawAsync( + $"EXEC sp_getapplock @Resource = 'transportation_lock_{dto.TransportationId}', @LockMode = 'Exclusive', @LockTimeout = 10000;"); +``` + +✅ This will ensure **only one thread** gets to proceed per `TransportationId`. + +--- + +## ✅ 3. Wrap the reservation logic in a **transaction** + +```csharp +using var transaction = await _context.Database.BeginTransactionAsync(IsolationLevel.Serializable); + +// locking query here +// seat validation +// insert tickets +// save ticket order +// commit + +await _unitOfWork.SaveChangesAsync(); +await transaction.CommitAsync(); +``` + +Use `IsolationLevel.Serializable` or `RepeatableRead` if you’re not doing explicit locking. + +--- + +## ✅ 4. Add a **unique constraint** on `SeatId + TransportationId` (if not already) + +To **enforce uniqueness at DB level** and prevent race conditions from succeeding: + +```sql +ALTER TABLE Tickets ADD CONSTRAINT UQ_Tickets_Seat_Transport UNIQUE (SeatId, TicketStatusId) +WHERE TicketStatusId != 3; -- exclude cancelled +``` + +Or make a logic-safe alternative depending on your schema. + +--- + +## ✅ Final version: Summary of changes + +### In your service: + +```csharp +using var transaction = await _dbContext.Database.BeginTransactionAsync(IsolationLevel.Serializable); + +// Optional: Lock the transportation row to prevent race +await _dbContext.Database.ExecuteSqlRawAsync( + $"EXEC sp_getapplock @Resource = 'transportation_lock_{dto.TransportationId}', @LockMode = 'Exclusive', @LockTimeout = 10000;"); + +// Re-fetch transportation + tickets +var transportation = await _transportationRepository.GetByIdWithTickets(dto.TransportationId); + +// Validate seats +var seatCheck = ValidateTransportationAndSeats(transportation, dto.Travelers); +if (!string.IsNullOrEmpty(seatCheck)) return Result.Error(0, seatCheck); + +// Proceed with reservation +... + +await _unitOfWork.SaveChangesAsync(); +await transaction.CommitAsync(); +``` + +--- + +## 🧠 Summary Table + +|Strategy|Prevents Race?|Web-farm Safe|Recommended For| +|---|---|---|---| +|`sp_getapplock`|✅ Yes|✅ Yes|SQL Server web apps| +|EF raw SQL `WITH (UPDLOCK)`|✅ Yes|✅ Yes|SQL Server monoliths| +|`SemaphoreSlim`|✅ Yes|❌ No|Local-only apps| +|`FOR UPDATE`|✅ Yes|✅ Yes|PostgreSQL, MySQL| + +--- + +Let me know your DB provider and environment (single-instance or multi-instance), and I can generate exact code tailored for that. +Perfect — you're absolutely right to want **the whole process to be atomic**: +→ **Seat allocation**, +→ **Ticket creation**, +→ **Balance checking & payment**, +→ **Transaction creation**, +→ **Traveler creation/upsert**, etc. + +This needs more than just _database-level locks_. You want to **serialize execution** for the same transportation to avoid concurrency conflicts — **across the entire flow**, not just the DB writes. + +--- + +## ✅ Your Goal + +> **For a given `TransportationId`, only one call to `CreateTicketOrderAsync` should execute at a time**, regardless of app instance or user. + +This includes logic **outside EF** (like payment, seat assignment, person creation, etc.). + +--- + +## 🛠️ The Right Solution: **Distributed Application Locking** + +### Use **SQL Server’s `sp_getapplock`** to lock **by `TransportationId`** + +Why? + +- It locks **application-level logic**, not just SQL rows + +- It works across threads, processes, and even app servers + +- It ensures only **one process** can work on that transportation at a time + + +--- + +## ✅ How to Implement in Your Method + +### 🔒 Step 1: Lock by Transportation ID + +Add this at the **start** of your method: + +```csharp +await _dbContext.Database.ExecuteSqlRawAsync( + $"EXEC sp_getapplock @Resource = 'transportation_lock_{dto.TransportationId}', " + + "@LockMode = 'Exclusive', @LockTimeout = 10000;"); +``` + +This ensures that **only one call per transportation** runs at a time. + +If a second request tries to lock the same ID, it waits up to 10 seconds. + +--- + +### 🔁 Step 2: Begin EF Transaction + +This will include all EF operations in a single atomic unit: + +```csharp +using var transaction = await _dbContext.Database.BeginTransactionAsync(); +``` + +--- + +### 🧠 Step 3: Keep the Full Logic As Is, But Within Transaction + +Like this: + +```csharp +public async Task> CreateTicketOrderAsync(long accountId, CreateTicketOrderDto dto) +{ + // 🔒 Lock to prevent concurrency per transportation + await _dbContext.Database.ExecuteSqlRawAsync( + $"EXEC sp_getapplock @Resource = 'transportation_lock_{dto.TransportationId}', " + + "@LockMode = 'Exclusive', @LockTimeout = 10000;"); + + // 🧾 Begin transaction + using var transaction = await _dbContext.Database.BeginTransactionAsync(); + + // 💰 Load account and transportation + var account = await _accountRepository.GetByIdAsync(accountId); + if (account == null) return Result.Error(0, "Account not found"); + + var transportation = await _transportationRepository.GetByIdAsync(dto.TransportationId); + if (transportation == null) return Result.Error(0, "Transportation not found"); + + // 💵 Check balance + var price = transportation.BasePrice * dto.Travelers.Count; + if (account.CurrentBalance < price) + return Result.Error(0, "Not enough money"); + + // ✅ Validate seat availability + var seatCheck = ValidateTransportationAndSeats(transportation, dto.Travelers); + if (!string.IsNullOrEmpty(seatCheck)) + return Result.Error(0, seatCheck); + + // 🪑 Assign seats (if dynamic logic) + await AssignSeatsIfDynamic(transportation.VehicleId, dto.Travelers); + + // 👤 Upsert travelers (can also use same transaction) + await UpsertTravelers(account.Id, dto.Travelers); + + // 🎟️ Create ticket order + var ticketOrder = new TicketOrder + { + BuyerId = account.Id, + CreatedAt = DateTime.UtcNow, + Description = "", + SerialNumber = Guid.NewGuid().ToString("N"), + TransportationId = dto.TransportationId, + }; + await _ticketOrderRepository.AddAsync(ticketOrder); + + // 🎫 Add tickets + foreach (var traveler in dto.Travelers) + { + var ticket = new Ticket + { + CreatedAt = DateTime.UtcNow, + Description = traveler.Description, + SeatId = traveler.SeatId!.Value, + SerialNumber = Guid.NewGuid().ToString("N"), + TicketOrder = ticketOrder, + TicketStatusId = 1, + TravelerId = traveler.Id, + }; + await _ticketRepository.AddAsync(ticket); + } + + // 💳 Commit everything + await _unitOfWork.SaveChangesAsync(); + + // 💸 Withdraw money and create transaction + await _accountService.PayForTicketOrderAsync(account.Id, ticketOrder.Id, price); + + // ✅ Commit transaction + await transaction.CommitAsync(); + + return Result.Success(ticketOrder.Id); +} +``` + +--- + +## 🧱 Summary of Protection + +|Step|Protected?|How| +|---|---|---| +|Prevent concurrent seat assignment|✅|`sp_getapplock` per `TransportationId`| +|Prevent concurrent DB changes|✅|EF `DbTransaction`| +|Prevent double-spend|✅|Balance check inside the same lock + transaction| +|Ensure traveler upserts/tickets are safe|✅|Wrapped in same transaction| + +--- + +## ⚠️ Important Note + +Make sure all the operations (`AssignSeatsIfDynamic`, `UpsertTravelers`, etc.): + +- Use the **same `DbContext`/UnitOfWork** + +- Don’t commit changes prematurely (no `SaveChangesAsync()` before you're ready to commit the whole transaction) + + +--- + +## ✅ Optional (Safety): Add retry logic + +In case of a **deadlock or lock timeout**, you might want to retry the whole operation once. + +--- + +Let me know if you want me to extract this into a reusable helper like: + +```csharp +await _appLockService.ExecuteWithLockAsync($"transportation_lock_{dto.TransportationId}", async () => { + // your reservation logic +}); +``` + +That would clean things up nicely. +Sure. Let’s break down everything you need to know about **transactions** in Entity Framework Core (EF Core) — especially for your case where you're doing **complex operations that must all succeed or fail together**. + +--- + +## 🧾 What is a Transaction? + +A **transaction** is a unit of work that is treated as a **single, indivisible operation**. Either **all of it succeeds** (committed), or **none of it does** (rolled back). + +### 🧠 Properties of a transaction (ACID): + +|Property|Meaning| +|---|---| +|**Atomicity**|All steps succeed or none do| +|**Consistency**|DB remains valid before and after| +|**Isolation**|Transactions don’t interfere with each other| +|**Durability**|Once committed, data is persisted permanently| + +--- + +## ✅ Why You Need Transactions + +In your case, you’re: + +- Assigning seats + +- Creating or updating people + +- Creating a `TicketOrder` + +- Creating multiple `Tickets` + +- Updating account balance & transaction history + + +All of these must either: + +- Complete **fully and safely**, or + +- **Fail entirely**, with no partial data left behind. + + +--- + +## 🧰 Transaction in EF Core: Full Example + +### 🔧 Step-by-step Example: + +```csharp +public async Task> CreateTicketOrderAsync(long accountId, CreateTicketOrderDto dto) +{ + // Begin EF Core transaction + using var transaction = await _dbContext.Database.BeginTransactionAsync(); + + try + { + // Load required entities + var account = await _accountRepository.GetByIdAsync(accountId); + if (account == null) + return Result.Error(0, "Account not found"); + + var transportation = await _transportationRepository.GetByIdAsync(dto.TransportationId); + if (transportation == null) + return Result.Error(0, "Transportation not found"); + + var price = transportation.BasePrice * dto.Travelers.Count; + if (account.CurrentBalance < price) + return Result.Error(0, "Not enough money"); + + // Validate seat assignment + var seatCheck = ValidateTransportationAndSeats(transportation, dto.Travelers); + if (!string.IsNullOrEmpty(seatCheck)) + return Result.Error(0, seatCheck); + + await AssignSeatsIfDynamic(transportation.VehicleId, dto.Travelers); + await UpsertTravelers(account.Id, dto.Travelers); + + // Create ticket order + var ticketOrder = new TicketOrder + { + BuyerId = account.Id, + CreatedAt = DateTime.UtcNow, + SerialNumber = Guid.NewGuid().ToString("N"), + TransportationId = dto.TransportationId, + }; + await _ticketOrderRepository.AddAsync(ticketOrder); + + foreach (var traveler in dto.Travelers) + { + await _ticketRepository.AddAsync(new Ticket + { + CreatedAt = DateTime.UtcNow, + Description = traveler.Description, + SeatId = traveler.SeatId.Value, + SerialNumber = Guid.NewGuid().ToString("N"), + TicketOrder = ticketOrder, + TicketStatusId = 1, + TravelerId = traveler.Id, + }); + } + + // Save changes + await _unitOfWork.SaveChangesAsync(); + + // Withdraw money from account + await _accountService.PayForTicketOrderAsync(account.Id, ticketOrder.Id, price); + + // Commit transaction + await transaction.CommitAsync(); + + return Result.Success(ticketOrder.Id); + } + catch (Exception ex) + { + // Rollback if anything failed + await transaction.RollbackAsync(); + return Result.Error(0, "Reservation failed: " + ex.Message); + } +} +``` + +--- + +## 🔄 Isolation Levels (Advanced) + +### You can specify isolation level when beginning a transaction: + +```csharp +using var transaction = await _dbContext.Database.BeginTransactionAsync(IsolationLevel.Serializable); +``` + +### Common levels: + +|Isolation Level|Description|Use Case| +|---|---|---| +|`ReadCommitted` (default)|No dirty reads|Usually enough| +|`RepeatableRead`|Prevents non-repeatable reads|Seat assignment logic| +|`Serializable`|Full isolation (slower, safer)|Financial or reservation systems| + +--- + +## 🧩 When `SaveChangesAsync()` Commits vs. Not + +Calling `SaveChangesAsync()` **does not commit** the outer transaction — it just writes pending changes to the database. + +The real commit happens only when you call: + +```csharp +await transaction.CommitAsync(); +``` + +If anything fails before that, the changes are **not persisted**. + +--- + +## ✅ Best Practices for Transactions in EF Core + +|Best Practice|Why| +|---|---| +|Keep transactions **short**|Locks and contention increase with time| +|Catch exceptions and **rollback**|Prevent dirty/incomplete data| +|Use **only one DbContext** inside the transaction|EF tracks entities via one unit of work| +|Don’t call SaveChanges too early|May break the atomicity| +|Use **appropriate isolation level**|Based on your concurrency needs| +|Consider retry policy for transient errors|Especially in distributed systems| + +--- + +## ❗ Common Pitfalls + +|Mistake|Problem| +|---|---| +|Mixing DbContext instances inside one transaction|Breaks consistency| +|Committing too early|Later failure still leaves partial data| +|Forgetting rollback in catch|Leaves transaction open or inconsistent| +|Async code outside transaction scope|Could break atomicity or introduce race| + +--- + +## 🧠 Summary: Transaction Essentials + +|Concept|Description| +|---|---| +|`BeginTransactionAsync()`|Starts a manual transaction| +|`SaveChangesAsync()`|Writes changes but doesn’t commit outer transaction| +|`CommitAsync()`|Finalizes all DB changes| +|`RollbackAsync()`|Reverts all changes since the transaction began| +|Scope|All EF/DB actions done within the transaction block| + +--- + +If you'd like, I can create a **generic transaction helper**, or even make this a **middleware** or **interceptor**, depending on how reusable you want this to be. + +Let me know! +Great! These questions show deep thinking about **how transactions and locks actually work** in EF Core and layered architecture. Let’s answer them one by one with real clarity and direction. + +--- + +## ❓ 1. _"I have this method in my `TicketOrderService`, and I don't have access to `_dbContext`."_ + +### ✅ Solution: + +If you're using **Repository + UnitOfWork pattern**, your `UnitOfWork` should expose a method to access the underlying **DbContext** or allow you to start a transaction. + +**👉 Extend your `IUnitOfWork` interface like this:** + +```csharp +public interface IUnitOfWork +{ + Task SaveChangesAsync(); + Task BeginTransactionAsync(IsolationLevel level = IsolationLevel.ReadCommitted); + DbContext Context { get; } // optional +} +``` + +And in your implementation: + +```csharp +public class UnitOfWork : IUnitOfWork +{ + private readonly AppDbContext _context; + + public UnitOfWork(AppDbContext context) => _context = context; + + public Task SaveChangesAsync() => _context.SaveChangesAsync(); + + public Task BeginTransactionAsync(IsolationLevel level = IsolationLevel.ReadCommitted) + => _context.Database.BeginTransactionAsync(level); + + public DbContext Context => _context; +} +``` + +### ✅ Then in your `TicketOrderService`: + +```csharp +using var transaction = await _unitOfWork.BeginTransactionAsync(); +// your operations +await _unitOfWork.SaveChangesAsync(); +await transaction.CommitAsync(); +``` + +This keeps your `Service` clean and architecture-respecting. + +--- + +## ❓ 2. _"How does the transaction hold stuff? Wouldn’t `unitOfWork.SaveChangesAsync()` just save everything?"_ + +### 🔍 Clarification: + +- `SaveChangesAsync()` **writes the changes to the database**, but… + +- **If you're in a transaction**, the database holds those changes in a **temporary, invisible state** until you explicitly call: + + +```csharp +await transaction.CommitAsync(); +``` + +💡 If you **don’t commit**, or you **rollback**, then **those changes are discarded**, even if you called `SaveChangesAsync()`. + +### 👇 Timeline of how EF works in a transaction: + +1. EF tracks entities in memory. + +2. You call `SaveChangesAsync()`. + +3. Changes are written to the DB — but: + + - If inside a transaction, they are **not visible to others yet**. + + - They are held until `CommitAsync()`. + +4. If you call `RollbackAsync()`, all writes are undone. + + +--- + +## ❓ 3. _"How would the lock know that the work with that transportation is finished?"_ + +### 🔒 About `sp_getapplock`: + +This SQL Server feature locks a **named resource** (like `transportation_lock_123`) for **the duration of the current SQL connection and transaction**. + +Here’s how it works: + +|Action|Result| +|---|---| +|You call `sp_getapplock`|SQL Server grants an exclusive lock for the resource| +|You complete the transaction (commit or rollback)|Lock is **automatically released**| +|Your connection is closed or disposed|Lock is released| + +### 🔍 So you don’t need to manually release the lock. + +Just make sure: + +- The **lock and transaction use the same connection** + +- You commit or rollback after the work is done + + +✅ EF Core handles all that automatically when using `Database.BeginTransactionAsync()`. + +--- + +## ✅ Final Advice Recap + +|Question|Answer| +|---|---| +|I don’t have access to `_dbContext`|Expose `BeginTransactionAsync` on your `IUnitOfWork`| +|How does transaction matter if I save mid-way?|It isolates changes — no one sees them until committed| +|How does lock get released?|Automatically when transaction completes or connection closes| + +--- + +Let me know if you want: + +- Sample `UnitOfWork` and `Repository` setup for full support + +- A lock + transaction helper method + +- Unit tests to simulate concurrent reservations + + +You're doing great — this is how robust, real-world software gets built. + +You've unpacked crucial concerns around **transactions**, **unit-of-work (UoW)**, and **application-wide consistency**. Here's a polished breakdown with clear answers and guidance: + +--- + +### ✅ 1. Is it okay to use both Transactions **and** Unit of Work? + +- **Yes, absolutely.** UoW is a design pattern that groups multiple repository operations into one logical unit, while a _transaction_ ensures these operations either all succeed or all fail atomically ([antondevtips.com](https://antondevtips.com/blog/implementing-unit-of-work-pattern-in-ef-core?utm_source=chatgpt.com "Implementing Unit of Work Pattern in EF Core - Anton DevTips")). + +- In EF Core, the **DbContext itself implements UoW**, collecting changes in memory until `SaveChangesAsync()` is called ([reddit.com](https://www.reddit.com/r/dotnet/comments/17npjtx/unit_of_work_pattern_still_necessary_in_net_8/?utm_source=chatgpt.com "Unit of Work Pattern still necessary in .NET 8? : r/dotnet - Reddit")). + +- When you execute **multiple SaveChanges**, or include non-repository logic (e.g., balance updates, payment creation, seat locking), **explicit transactions** ensure the entire flow remains atomic . + + +--- + +### ✅ 2. How exactly to open/close transactions? Where to be careful? + +#### ✨ Use EF to manage transactions in your UoW: + +1. **Extend your `IUnitOfWork`** to include transaction methods: + + ```csharp + Task BeginTransactionAsync(IsolationLevel level = ReadCommitted); + Task SaveChangesAsync(); + ``` + +2. **In your service**, do: + + ```csharp + using var tx = await _unitOfWork.BeginTransactionAsync(); + try { + // perform all operations (seat locks, entity changes, balance, tickets) + await _unitOfWork.SaveChangesAsync(); + await tx.CommitAsync(); + } catch { + await tx.RollbackAsync(); + throw; + } + ``` + +3. **Know the boundaries**: Keep the transaction as short as possible. Open it before critical operations and close it after the final `CommitAsync()`. + + +> 💡 Use `(IsolationLevel.Serializable)` for scenarios like seat reservation where concurrent writes must be prevented ([milanjovanovic.tech](https://www.milanjovanovic.tech/blog/working-with-transactions-in-ef-core?utm_source=chatgpt.com "Working With Transactions In EF Core"), [learn.microsoft.com](https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application?utm_source=chatgpt.com "Implementing the Repository and Unit of Work Patterns in an ASP ...")). + +--- + +### ✅ 3. Why did things “work” without explicit transactions? + +- **Simple SaveChanges** calls act like atomic units—if they fail, nothing is saved. With just one SaveChanges call, EF wraps it in a default transaction ([stackoverflow.com](https://stackoverflow.com/questions/24636352/unit-of-work-i-dont-need-to-use-transactions?utm_source=chatgpt.com "c# - unit of work - I don't need to use transactions? - Stack Overflow")). + +- However, as soon as your workflow involves **multiple SaveChanges**, **external services**, or **cross-repository updates**, the default behavior is no longer sufficient. A failure midway could leave your data in a partial state. + +- That's where **explicit transaction scopes** come in—to guarantee everything is batched and rolled back if any part fails ([antondevtips.com](https://antondevtips.com/blog/implementing-unit-of-work-pattern-in-ef-core?utm_source=chatgpt.com "Implementing Unit of Work Pattern in EF Core - Anton DevTips")). + + +--- + +### 🧠 TL;DR Summary + +|Concept|Purpose|When Needed| +|---|---|---| +|**Unit of Work**|Organizes multiple EF operations into one commit|Always used with EF DbContext| +|**Implicit transaction**|EF wraps each SaveChanges automatically|Ok for single SaveChanges calls| +|**Explicit transaction**|Manually control commit/rollback across many operations|Needed when multiple SaveChanges, external services, concurrency, etc.| +|**IsolationLevel.Serializable**|Highest locking level to prevent concurrent conflicts|Use for critical resource locks (e.g., seat booking)| +|**Be careful**|Keep transactions short to avoid locks and deadlocks|Avoid long-running operations inside the transaction| + +--- + +If you want, I can provide: + +- **Code templates** for UoW with transaction management + +- **Interceptor or decorator** to automate transaction handling in your services + +- **Concurrency demos** to test seat reservation under load + + +Just say the word! +Absolutely! Let’s clarify both of your statements with authoritative sources: + +--- + +## 1. If I haven't called `BeginTransaction` and call `SaveChanges`, will changes be saved? + +✅ **Yes.** EF Core automatically wraps **every** `SaveChanges()` call in its **own transaction**. This means: + +- If **all operations succeed**, the data is saved. +- If **anything fails**, the entire set is **rolled back**, leaving the DB unchanged. citeturn0search0turn0search9 + +🔁 So even without explicitly starting a transaction, `SaveChanges()` ensures atomicity for that batch of changes. + +--- + +## 2. If I have called `BeginTransaction`, and then call `SaveChanges`, do changes go to the DB immediately? + +✅ **Yes, but context matters.** When you wrap operations in an explicit transaction: + +- Each `SaveChanges()` writes within that transaction. +- However, **none** of these writes become visible to other connections until you call `Commit()`. + +EF also uses **savepoints** internally (for multiple `SaveChanges()` calls) to enable partial rollbacks without rolling back the entire transaction. citeturn0search0turn0search2turn0search3 + +--- + +### 🧩 In Plain English + +| Scenario | SaveChanges Only | BeginTransaction + SaveChanges | +|------------------|--------------------------------------------------|----------------------------------------------------| +| No transaction | Auto-wrapped in its own transaction–immediate. | — | +| With explicit transaction | Writes are within the transaction, not yet committed. | ✔ | +| Rollback before commit | Not possible. SaveChanges is final. | ✔ Rolls everything back. | + +--- + +### ✅ TL;DR + +- ✅ **Without `BeginTransaction`**: `SaveChanges()` is atomic per call—commits or rolls back automatically. +- ✅ **With `BeginTransaction`**: `SaveChanges()` writes into the transaction, but the changes are **held until** you call `Commit()`; `Rollback()` discards them all. + +--- + +Want some **ready-to-use code** to introduce `BeginTransaction()` into your UnitOfWork and services? Just let me know and I’ll supply a clean implementation! \ No newline at end of file diff --git a/02_ProjectOrientedSessions/Session09/Session09 Backend.md b/02_ProjectOrientedSessions/Session09/Session09 Backend.md new file mode 100644 index 0000000..2068844 --- /dev/null +++ b/02_ProjectOrientedSessions/Session09/Session09 Backend.md @@ -0,0 +1,4 @@ +Endpoint for increasing balance +Endpoint for reserving ticket(s) + updating transportation remaining count + adding transaction +Endpoint for getting seats + seeing if each is reserved or not +Creating and sending a pdf downloadable ticket diff --git a/02_ProjectOrientedSessions/docs/AlibabaERD-Version02.pdf b/02_ProjectOrientedSessions/docs/AlibabaERD-Version02.pdf index c08e576..50c4666 100644 Binary files a/02_ProjectOrientedSessions/docs/AlibabaERD-Version02.pdf and b/02_ProjectOrientedSessions/docs/AlibabaERD-Version02.pdf differ diff --git a/02_ProjectOrientedSessions/docs/AlibabaERD-Version02.vsdx b/02_ProjectOrientedSessions/docs/AlibabaERD-Version02.vsdx index 258019b..f2d2e9f 100644 Binary files a/02_ProjectOrientedSessions/docs/AlibabaERD-Version02.vsdx and b/02_ProjectOrientedSessions/docs/AlibabaERD-Version02.vsdx differ