diff --git a/Build.ps1 b/Build.ps1
index dfae61b..fc70d37 100644
--- a/Build.ps1
+++ b/Build.ps1
@@ -72,7 +72,7 @@ ForEach ($folder in $testDirs) {
$i++
$format = @{ $true = "/p:CoverletOutputFormat=opencover"; $false = ""}[$i -eq $testDirs.Length ]
- exec { & dotnet test $folder.FullName -c Release --no-build --no-restore /p:CollectCoverage=true /p:CoverletOutput=$root\coverage /p:MergeWith=$root\coverage.json /p:Include="[*]DFlow.*" /p:Exclude="[*]DFlow.Tests.*%2c[*]DFlow.Example.*" $format }
+ exec { & dotnet test $folder.FullName -c Release --no-build --no-restore /p:CollectCoverage=true /p:CoverletOutput=$root\coverage /p:MergeWith=$root\coverage.json /p:Include="[*]DFlow.*" /p:Exclude="[*]DFlow.Tests.*%2c[*]DFlow.Example.*%2c[*]DFlow.Samples.*%2c[*]SimplestApp" $format }
}
choco install codecov --no-progress
@@ -81,4 +81,4 @@ exec { & codecov -f "$root\coverage.opencover.xml" }
# Pack
echo "`n`n----- PACK -----`n"
-exec { & dotnet pack -c Release -o $artifactsPath --include-symbols --no-build $versionSuffix }
\ No newline at end of file
+exec { & dotnet pack -c Release -o $artifactsPath --include-symbols --no-build $versionSuffix }
diff --git a/DFlow.sln b/DFlow.sln
index 26e4f94..e73b77e 100644
--- a/DFlow.sln
+++ b/DFlow.sln
@@ -10,42 +10,162 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DFlow.DependencyInjection.S
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DFlow.AspNetCore", "src\contrib\DFlow.AspNetCore\DFlow.AspNetCore.csproj", "{F370775C-FA29-4340-BCE5-CB71304C58A4}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DFlow.Domain", "src\DFlow.Domain\DFlow.Domain.csproj", "{C4379CA3-A13D-4E42-B381-3E71EE945FDF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DFlow.Domain.Events", "src\DFlow.Domain.Events\DFlow.Domain.Events.csproj", "{82AB6062-B521-48AF-9611-F632251077D0}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DFlow.Business.Cqrs", "src\DFlow.Business.Cqrs\DFlow.Business.Cqrs.csproj", "{7057935D-2C6A-4CF7-B083-613441EA40AE}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FirstImpl", "FirstImpl", "{085060D8-3CA9-4165-AFB3-A11EBF5746E6}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{96AC39D1-C074-4993-B3E2-F190B2B3E5D4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimplestApp", "samples\SimplestApp\SimplestApp.csproj", "{BDF24821-36AA-43D8-A55F-DF960D88E349}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DFlow.Samples", "samples\DFlow.Samples\DFlow.Samples.csproj", "{ECB83291-4308-440B-863E-A4BFDDC46D36}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1D9940E4-09D4-42B9-B72D-2DA4D1AA00EB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DFlow.Persistence", "src\DFlow.Persistence\DFlow.Persistence.csproj", "{A9F3BA94-9543-4148-919C-39ED9640D5BC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Contrib", "Contrib", "{6717E82A-B0EA-4FCA-8A2C-31A46D4999A4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimplestApp.Business.Cqrs", "samples\SimplestApp.Business.Cqrs\SimplestApp.Business.Cqrs.csproj", "{7C3FA12E-C1AB-4937-BB91-D3D32366672F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimplestApp.Persistence.EntityFramework", "samples\SimplestApp.Persistence.EntityFramework\SimplestApp.Persistence.EntityFramework.csproj", "{86B8F8D6-303C-4888-8F62-500399EFF82E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DFlow.Domain.EventBus.FluentMediator", "src\contrib\DFlow.Domain.EventBus.FluentMediator\DFlow.Domain.EventBus.FluentMediator.csproj", "{24A7697A-FC70-40A8-A6EB-3A5F634A9A1E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DFlow.Persistence.EntityFramework", "src\contrib\DFlow.Persistence.EntityFramework\DFlow.Persistence.EntityFramework.csproj", "{9DB514B5-3C00-472F-BB25-E484978ED5D9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
Tests|Any CPU = Tests|Any CPU
+ Release Profilling|Any CPU = Release Profilling|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Release|Any CPU.Build.0 = Release|Any CPU
- {3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Tests|Any CPU.ActiveCfg = Tests|Any CPU
- {3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Tests|Any CPU.Build.0 = Tests|Any CPU
+ {3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03}.Release Profilling|Any CPU.Build.0 = Release Profilling|Any CPU
{D5C025B8-AC7E-4C19-99EA-03732456F812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5C025B8-AC7E-4C19-99EA-03732456F812}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5C025B8-AC7E-4C19-99EA-03732456F812}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5C025B8-AC7E-4C19-99EA-03732456F812}.Release|Any CPU.Build.0 = Release|Any CPU
- {D5C025B8-AC7E-4C19-99EA-03732456F812}.Tests|Any CPU.ActiveCfg = Tests|Any CPU
- {D5C025B8-AC7E-4C19-99EA-03732456F812}.Tests|Any CPU.Build.0 = Tests|Any CPU
+ {D5C025B8-AC7E-4C19-99EA-03732456F812}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {D5C025B8-AC7E-4C19-99EA-03732456F812}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {D5C025B8-AC7E-4C19-99EA-03732456F812}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {D5C025B8-AC7E-4C19-99EA-03732456F812}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {D5C025B8-AC7E-4C19-99EA-03732456F812}.Release Profilling|Any CPU.Build.0 = Release Profilling|Any CPU
{E592B474-F073-41A8-8AEE-C24A7AD19586}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E592B474-F073-41A8-8AEE-C24A7AD19586}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E592B474-F073-41A8-8AEE-C24A7AD19586}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E592B474-F073-41A8-8AEE-C24A7AD19586}.Release|Any CPU.Build.0 = Release|Any CPU
{E592B474-F073-41A8-8AEE-C24A7AD19586}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
{E592B474-F073-41A8-8AEE-C24A7AD19586}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {E592B474-F073-41A8-8AEE-C24A7AD19586}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
{AE714C76-3519-49DB-8B0E-484F363311FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {AE714C76-3519-49DB-8B0E-484F363311FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE714C76-3519-49DB-8B0E-484F363311FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {AE714C76-3519-49DB-8B0E-484F363311FB}.Release|Any CPU.Build.0 = Release|Any CPU
{AE714C76-3519-49DB-8B0E-484F363311FB}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
- {AE714C76-3519-49DB-8B0E-484F363311FB}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {AE714C76-3519-49DB-8B0E-484F363311FB}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
{F370775C-FA29-4340-BCE5-CB71304C58A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F370775C-FA29-4340-BCE5-CB71304C58A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F370775C-FA29-4340-BCE5-CB71304C58A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F370775C-FA29-4340-BCE5-CB71304C58A4}.Release|Any CPU.Build.0 = Release|Any CPU
{F370775C-FA29-4340-BCE5-CB71304C58A4}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
- {F370775C-FA29-4340-BCE5-CB71304C58A4}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {F370775C-FA29-4340-BCE5-CB71304C58A4}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {C4379CA3-A13D-4E42-B381-3E71EE945FDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C4379CA3-A13D-4E42-B381-3E71EE945FDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C4379CA3-A13D-4E42-B381-3E71EE945FDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C4379CA3-A13D-4E42-B381-3E71EE945FDF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C4379CA3-A13D-4E42-B381-3E71EE945FDF}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {C4379CA3-A13D-4E42-B381-3E71EE945FDF}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {C4379CA3-A13D-4E42-B381-3E71EE945FDF}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {C4379CA3-A13D-4E42-B381-3E71EE945FDF}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {C4379CA3-A13D-4E42-B381-3E71EE945FDF}.Release Profilling|Any CPU.Build.0 = Release Profilling|Any CPU
+ {82AB6062-B521-48AF-9611-F632251077D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {82AB6062-B521-48AF-9611-F632251077D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {82AB6062-B521-48AF-9611-F632251077D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {82AB6062-B521-48AF-9611-F632251077D0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {82AB6062-B521-48AF-9611-F632251077D0}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {82AB6062-B521-48AF-9611-F632251077D0}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {82AB6062-B521-48AF-9611-F632251077D0}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {82AB6062-B521-48AF-9611-F632251077D0}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {82AB6062-B521-48AF-9611-F632251077D0}.Release Profilling|Any CPU.Build.0 = Release Profilling|Any CPU
+ {7057935D-2C6A-4CF7-B083-613441EA40AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7057935D-2C6A-4CF7-B083-613441EA40AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7057935D-2C6A-4CF7-B083-613441EA40AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7057935D-2C6A-4CF7-B083-613441EA40AE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7057935D-2C6A-4CF7-B083-613441EA40AE}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {7057935D-2C6A-4CF7-B083-613441EA40AE}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {7057935D-2C6A-4CF7-B083-613441EA40AE}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {7057935D-2C6A-4CF7-B083-613441EA40AE}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {7057935D-2C6A-4CF7-B083-613441EA40AE}.Release Profilling|Any CPU.Build.0 = Release Profilling|Any CPU
+ {BDF24821-36AA-43D8-A55F-DF960D88E349}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BDF24821-36AA-43D8-A55F-DF960D88E349}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BDF24821-36AA-43D8-A55F-DF960D88E349}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {BDF24821-36AA-43D8-A55F-DF960D88E349}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {BDF24821-36AA-43D8-A55F-DF960D88E349}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ECB83291-4308-440B-863E-A4BFDDC46D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ECB83291-4308-440B-863E-A4BFDDC46D36}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ECB83291-4308-440B-863E-A4BFDDC46D36}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {ECB83291-4308-440B-863E-A4BFDDC46D36}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {ECB83291-4308-440B-863E-A4BFDDC46D36}.Release Profilling|Any CPU.Build.0 = Release Profilling|Any CPU
+ {ECB83291-4308-440B-863E-A4BFDDC46D36}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A9F3BA94-9543-4148-919C-39ED9640D5BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A9F3BA94-9543-4148-919C-39ED9640D5BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A9F3BA94-9543-4148-919C-39ED9640D5BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A9F3BA94-9543-4148-919C-39ED9640D5BC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A9F3BA94-9543-4148-919C-39ED9640D5BC}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {A9F3BA94-9543-4148-919C-39ED9640D5BC}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {A9F3BA94-9543-4148-919C-39ED9640D5BC}.Release Profilling|Any CPU.ActiveCfg = Debug|Any CPU
+ {A9F3BA94-9543-4148-919C-39ED9640D5BC}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {7C3FA12E-C1AB-4937-BB91-D3D32366672F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7C3FA12E-C1AB-4937-BB91-D3D32366672F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7C3FA12E-C1AB-4937-BB91-D3D32366672F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7C3FA12E-C1AB-4937-BB91-D3D32366672F}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {7C3FA12E-C1AB-4937-BB91-D3D32366672F}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {7C3FA12E-C1AB-4937-BB91-D3D32366672F}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {7C3FA12E-C1AB-4937-BB91-D3D32366672F}.Release Profilling|Any CPU.Build.0 = Release Profilling|Any CPU
+ {86B8F8D6-303C-4888-8F62-500399EFF82E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {86B8F8D6-303C-4888-8F62-500399EFF82E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {86B8F8D6-303C-4888-8F62-500399EFF82E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {86B8F8D6-303C-4888-8F62-500399EFF82E}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {86B8F8D6-303C-4888-8F62-500399EFF82E}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {86B8F8D6-303C-4888-8F62-500399EFF82E}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {86B8F8D6-303C-4888-8F62-500399EFF82E}.Release Profilling|Any CPU.Build.0 = Release Profilling|Any CPU
+ {24A7697A-FC70-40A8-A6EB-3A5F634A9A1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24A7697A-FC70-40A8-A6EB-3A5F634A9A1E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24A7697A-FC70-40A8-A6EB-3A5F634A9A1E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24A7697A-FC70-40A8-A6EB-3A5F634A9A1E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {24A7697A-FC70-40A8-A6EB-3A5F634A9A1E}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {24A7697A-FC70-40A8-A6EB-3A5F634A9A1E}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {24A7697A-FC70-40A8-A6EB-3A5F634A9A1E}.Release Profilling|Any CPU.ActiveCfg = Release Profilling|Any CPU
+ {24A7697A-FC70-40A8-A6EB-3A5F634A9A1E}.Release Profilling|Any CPU.Build.0 = Release Profilling|Any CPU
+ {9DB514B5-3C00-472F-BB25-E484978ED5D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9DB514B5-3C00-472F-BB25-E484978ED5D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9DB514B5-3C00-472F-BB25-E484978ED5D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9DB514B5-3C00-472F-BB25-E484978ED5D9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9DB514B5-3C00-472F-BB25-E484978ED5D9}.Tests|Any CPU.ActiveCfg = Debug|Any CPU
+ {9DB514B5-3C00-472F-BB25-E484978ED5D9}.Tests|Any CPU.Build.0 = Debug|Any CPU
+ {9DB514B5-3C00-472F-BB25-E484978ED5D9}.Release Profilling|Any CPU.ActiveCfg = Debug|Any CPU
+ {9DB514B5-3C00-472F-BB25-E484978ED5D9}.Release Profilling|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {D5C025B8-AC7E-4C19-99EA-03732456F812} = {085060D8-3CA9-4165-AFB3-A11EBF5746E6}
+ {F370775C-FA29-4340-BCE5-CB71304C58A4} = {085060D8-3CA9-4165-AFB3-A11EBF5746E6}
+ {AE714C76-3519-49DB-8B0E-484F363311FB} = {085060D8-3CA9-4165-AFB3-A11EBF5746E6}
+ {3CE7D4D0-58BF-44C5-AC84-7CA1FBD17E03} = {085060D8-3CA9-4165-AFB3-A11EBF5746E6}
+ {BDF24821-36AA-43D8-A55F-DF960D88E349} = {96AC39D1-C074-4993-B3E2-F190B2B3E5D4}
+ {ECB83291-4308-440B-863E-A4BFDDC46D36} = {96AC39D1-C074-4993-B3E2-F190B2B3E5D4}
+ {E592B474-F073-41A8-8AEE-C24A7AD19586} = {1D9940E4-09D4-42B9-B72D-2DA4D1AA00EB}
+ {7C3FA12E-C1AB-4937-BB91-D3D32366672F} = {96AC39D1-C074-4993-B3E2-F190B2B3E5D4}
+ {86B8F8D6-303C-4888-8F62-500399EFF82E} = {96AC39D1-C074-4993-B3E2-F190B2B3E5D4}
+ {24A7697A-FC70-40A8-A6EB-3A5F634A9A1E} = {6717E82A-B0EA-4FCA-8A2C-31A46D4999A4}
+ {9DB514B5-3C00-472F-BB25-E484978ED5D9} = {6717E82A-B0EA-4FCA-8A2C-31A46D4999A4}
EndGlobalSection
EndGlobal
diff --git a/LICENSE.TXT b/LICENSE.TXT
new file mode 100644
index 0000000..14e2f77
--- /dev/null
+++ b/LICENSE.TXT
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/samples/DFlow.Example/DFlow.Example.csproj b/samples/DFlow.Example/DFlow.Example.csproj
index 8340da2..d98de0d 100644
--- a/samples/DFlow.Example/DFlow.Example.csproj
+++ b/samples/DFlow.Example/DFlow.Example.csproj
@@ -3,7 +3,7 @@
Librarynetcoreapp3.1
- Debug;Release;Tests
+ Debug;Release;Tests;Release ProfillingAnyCPUZCRQS
@@ -12,6 +12,10 @@
TRACE;TEST_BUILD
+
+ true
+
+
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/DFlow.Persistence.EntityFramework.csproj b/samples/DFlow.Samples.Persistence.EntityFramework/DFlow.Persistence.EntityFramework.csproj
new file mode 100644
index 0000000..f64c62e
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/DFlow.Persistence.EntityFramework.csproj
@@ -0,0 +1,24 @@
+
+
+
+ net5.0;netcoreapp3.1
+ DFlow.Persistence
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ExtensionMethods/BusinessObjectsExtensions.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ExtensionMethods/BusinessObjectsExtensions.cs
new file mode 100644
index 0000000..ec62f7a
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ExtensionMethods/BusinessObjectsExtensions.cs
@@ -0,0 +1,73 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using System.Diagnostics;
+using AppFabric.Domain.BusinessObjects;
+using AppFabric.Domain.Framework.BusinessObjects;
+using AppFabric.Persistence.Model;
+using Version = AppFabric.Domain.BusinessObjects.Version;
+
+namespace AppFabric.Persistence.ExtensionMethods
+{
+ public static class BusinessObjectsExtensions
+ {
+ public static ProjectState ToProjectState(this Project project)
+ => new ProjectState(project.Id.Value,
+ project.Name.Value,
+ project.Code.Value,
+ project.Budget.Value,
+ project.StartDate.Value,
+ project.ClientId.Value,
+ project.Owner.Value,
+ project.OrderNumber.Value,
+ project.Status.Value,
+ BitConverter.GetBytes(project.Version.Value));
+
+ public static Project ToProject(this ProjectState state)
+ => Project.From(
+ EntityId.From(state.Id),
+ ProjectName.From(state.Name),
+ ProjectCode.From(state.Code),
+ DateAndTime.From(state.StartDate),
+ Money.From(state.Budget),
+ EntityId.From(state.ClientId),
+ Email.From(state.Owner),
+ ProjectStatus.From(state.Status),
+ ServiceOrderNumber.From(state.OrderNumber),
+ Version.From(BitConverter.ToInt32(state.RowVersion)));
+
+ public static UserState ToUserState(this User user)
+ => new UserState(user.Id.Value,
+ user.Name.Value,
+ user.Cnpj.Value,
+ user.CommercialEmail.Value,
+ BitConverter.GetBytes(user.Version.Value));
+
+ public static User ToUser(this UserState state)
+ => User.From(
+ EntityId.From(state.Id),
+ Name.From(state.Name),
+ SocialSecurityId.From(state.Cnpj),
+ Email.From(state.CommercialEmail),
+ Version.From(BitConverter.ToInt32(state.RowVersion)));
+
+
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210004122_InitialCreate.Designer.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210004122_InitialCreate.Designer.cs
new file mode 100644
index 0000000..5a46b18
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210004122_InitialCreate.Designer.cs
@@ -0,0 +1,195 @@
+//
+using System;
+using AppFabric.Persistence;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace AppFabric.Persistence.Migrations
+{
+ [DbContext(typeof(AppFabricDbContext))]
+ [Migration("20210210004122_InitialCreate")]
+ partial class InitialCreate
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "5.0.3");
+
+ modelBuilder.Entity("AppFabric.Persistence.Model.ClientState", b =>
+ {
+ b.Property("ClientId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CreateAt")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("PersistenceId")
+ .HasColumnType("TEXT");
+
+ b.Property("ProjectId")
+ .HasColumnType("INTEGER");
+
+ b.Property("RowVersion")
+ .HasColumnType("BLOB");
+
+ b.HasKey("ClientId");
+
+ b.ToTable("ClientState");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.Model.ProjectState", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Budget")
+ .HasColumnType("TEXT");
+
+ b.Property("ClientId")
+ .HasColumnType("TEXT");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("CreateAt")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("OrderNumber")
+ .HasColumnType("TEXT");
+
+ b.Property("Owner")
+ .HasColumnType("TEXT");
+
+ b.Property("PersistenceId")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("BLOB");
+
+ b.Property("StartDate")
+ .HasColumnType("TEXT");
+
+ b.Property("Status")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("Projects");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.Model.UserState", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Cnpj")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("CommercialEmail")
+ .HasColumnType("TEXT");
+
+ b.Property("CreateAt")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("PersistenceId")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("BLOB");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.ReadModel.ProjectProjection", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Budget")
+ .HasColumnType("TEXT");
+
+ b.Property("ClientId")
+ .HasColumnType("TEXT");
+
+ b.Property("ClientName")
+ .HasColumnType("TEXT");
+
+ b.Property("Code")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("OrderNumber")
+ .HasColumnType("TEXT");
+
+ b.Property("Owner")
+ .HasColumnType("TEXT");
+
+ b.Property("StartDate")
+ .HasColumnType("TEXT");
+
+ b.Property("Status")
+ .HasColumnType("INTEGER");
+
+ b.Property("StatusName")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("ProjectsProjection");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.ReadModel.UserProjection", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Cnpj")
+ .HasColumnType("TEXT");
+
+ b.Property("CommercialEmail")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("UsersProjection");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210004122_InitialCreate.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210004122_InitialCreate.cs
new file mode 100644
index 0000000..0ff263f
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210004122_InitialCreate.cs
@@ -0,0 +1,124 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace AppFabric.Persistence.Migrations
+{
+ public partial class InitialCreate : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "ClientState",
+ columns: table => new
+ {
+ ClientId = table.Column(type: "INTEGER", nullable: false)
+ .Annotation("Sqlite:Autoincrement", true),
+ ProjectId = table.Column(type: "INTEGER", nullable: false),
+ CreateAt = table.Column(type: "TEXT", nullable: false),
+ RowVersion = table.Column(type: "BLOB", nullable: true),
+ IsDeleted = table.Column(type: "INTEGER", nullable: false),
+ PersistenceId = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ClientState", x => x.ClientId);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Projects",
+ columns: table => new
+ {
+ Id = table.Column(type: "TEXT", nullable: false),
+ ClientId = table.Column(type: "TEXT", nullable: false),
+ Name = table.Column(type: "TEXT", nullable: false),
+ Code = table.Column(type: "TEXT", nullable: false),
+ StartDate = table.Column(type: "TEXT", nullable: false),
+ Budget = table.Column(type: "TEXT", nullable: false),
+ Owner = table.Column(type: "TEXT", nullable: true),
+ OrderNumber = table.Column(type: "TEXT", nullable: true),
+ Status = table.Column(type: "INTEGER", nullable: false),
+ CreateAt = table.Column(type: "TEXT", nullable: false),
+ RowVersion = table.Column(type: "BLOB", nullable: true),
+ IsDeleted = table.Column(type: "INTEGER", nullable: false),
+ PersistenceId = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Projects", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "ProjectsProjection",
+ columns: table => new
+ {
+ Id = table.Column(type: "TEXT", nullable: false),
+ ClientId = table.Column(type: "TEXT", nullable: false),
+ ClientName = table.Column(type: "TEXT", nullable: true),
+ Name = table.Column(type: "TEXT", nullable: true),
+ Code = table.Column(type: "TEXT", nullable: true),
+ StartDate = table.Column(type: "TEXT", nullable: false),
+ Budget = table.Column(type: "TEXT", nullable: false),
+ Owner = table.Column(type: "TEXT", nullable: true),
+ OrderNumber = table.Column(type: "TEXT", nullable: true),
+ Status = table.Column(type: "INTEGER", nullable: false),
+ StatusName = table.Column(type: "TEXT", nullable: true),
+ IsDeleted = table.Column(type: "INTEGER", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ProjectsProjection", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Users",
+ columns: table => new
+ {
+ Id = table.Column(type: "TEXT", nullable: false),
+ Name = table.Column(type: "TEXT", nullable: false),
+ Cnpj = table.Column(type: "TEXT", nullable: false),
+ CommercialEmail = table.Column(type: "TEXT", nullable: true),
+ CreateAt = table.Column(type: "TEXT", nullable: false),
+ RowVersion = table.Column(type: "BLOB", nullable: true),
+ IsDeleted = table.Column(type: "INTEGER", nullable: false),
+ PersistenceId = table.Column(type: "TEXT", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Users", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "UsersProjection",
+ columns: table => new
+ {
+ Id = table.Column(type: "TEXT", nullable: false),
+ Name = table.Column(type: "TEXT", nullable: true),
+ Cnpj = table.Column(type: "TEXT", nullable: true),
+ CommercialEmail = table.Column(type: "TEXT", nullable: true),
+ IsDeleted = table.Column(type: "INTEGER", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_UsersProjection", x => x.Id);
+ });
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "ClientState");
+
+ migrationBuilder.DropTable(
+ name: "Projects");
+
+ migrationBuilder.DropTable(
+ name: "ProjectsProjection");
+
+ migrationBuilder.DropTable(
+ name: "Users");
+
+ migrationBuilder.DropTable(
+ name: "UsersProjection");
+ }
+ }
+}
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210161238_Versioning.Designer.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210161238_Versioning.Designer.cs
new file mode 100644
index 0000000..1bcc98a
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210161238_Versioning.Designer.cs
@@ -0,0 +1,201 @@
+//
+using System;
+using AppFabric.Persistence;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace AppFabric.Persistence.Migrations
+{
+ [DbContext(typeof(AppFabricDbContext))]
+ [Migration("20210210161238_Versioning")]
+ partial class Versioning
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "5.0.3");
+
+ modelBuilder.Entity("AppFabric.Persistence.Model.ClientState", b =>
+ {
+ b.Property("ClientId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CreateAt")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("PersistenceId")
+ .HasColumnType("TEXT");
+
+ b.Property("ProjectId")
+ .HasColumnType("INTEGER");
+
+ b.Property("RowVersion")
+ .HasColumnType("BLOB");
+
+ b.HasKey("ClientId");
+
+ b.ToTable("ClientState");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.Model.ProjectState", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Budget")
+ .HasColumnType("TEXT");
+
+ b.Property("ClientId")
+ .HasColumnType("TEXT");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("CreateAt")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("OrderNumber")
+ .HasColumnType("TEXT");
+
+ b.Property("Owner")
+ .HasColumnType("TEXT");
+
+ b.Property("PersistenceId")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("BLOB");
+
+ b.Property("StartDate")
+ .HasColumnType("TEXT");
+
+ b.Property("Status")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("Projects");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.Model.UserState", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Cnpj")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("CommercialEmail")
+ .HasColumnType("TEXT");
+
+ b.Property("CreateAt")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("PersistenceId")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("BLOB");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.ReadModel.ProjectProjection", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Budget")
+ .HasColumnType("TEXT");
+
+ b.Property("ClientId")
+ .HasColumnType("TEXT");
+
+ b.Property("ClientName")
+ .HasColumnType("TEXT");
+
+ b.Property("Code")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("OrderNumber")
+ .HasColumnType("TEXT");
+
+ b.Property("Owner")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("INTEGER");
+
+ b.Property("StartDate")
+ .HasColumnType("TEXT");
+
+ b.Property("Status")
+ .HasColumnType("INTEGER");
+
+ b.Property("StatusName")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("ProjectsProjection");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.ReadModel.UserProjection", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Cnpj")
+ .HasColumnType("TEXT");
+
+ b.Property("CommercialEmail")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("UsersProjection");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210161238_Versioning.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210161238_Versioning.cs
new file mode 100644
index 0000000..7e52a5d
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/20210210161238_Versioning.cs
@@ -0,0 +1,35 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace AppFabric.Persistence.Migrations
+{
+ public partial class Versioning : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "RowVersion",
+ table: "UsersProjection",
+ type: "INTEGER",
+ nullable: false,
+ defaultValue: 0);
+
+ migrationBuilder.AddColumn(
+ name: "RowVersion",
+ table: "ProjectsProjection",
+ type: "INTEGER",
+ nullable: false,
+ defaultValue: 0);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "RowVersion",
+ table: "UsersProjection");
+
+ migrationBuilder.DropColumn(
+ name: "RowVersion",
+ table: "ProjectsProjection");
+ }
+ }
+}
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/AppFabricDbContextModelSnapshot.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/AppFabricDbContextModelSnapshot.cs
new file mode 100644
index 0000000..87f1272
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Migrations/AppFabricDbContextModelSnapshot.cs
@@ -0,0 +1,199 @@
+//
+using System;
+using AppFabric.Persistence;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace AppFabric.Persistence.Migrations
+{
+ [DbContext(typeof(AppFabricDbContext))]
+ partial class AppFabricDbContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "5.0.3");
+
+ modelBuilder.Entity("AppFabric.Persistence.Model.ClientState", b =>
+ {
+ b.Property("ClientId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CreateAt")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("PersistenceId")
+ .HasColumnType("TEXT");
+
+ b.Property("ProjectId")
+ .HasColumnType("INTEGER");
+
+ b.Property("RowVersion")
+ .HasColumnType("BLOB");
+
+ b.HasKey("ClientId");
+
+ b.ToTable("ClientState");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.Model.ProjectState", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Budget")
+ .HasColumnType("TEXT");
+
+ b.Property("ClientId")
+ .HasColumnType("TEXT");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("CreateAt")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("OrderNumber")
+ .HasColumnType("TEXT");
+
+ b.Property("Owner")
+ .HasColumnType("TEXT");
+
+ b.Property("PersistenceId")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("BLOB");
+
+ b.Property("StartDate")
+ .HasColumnType("TEXT");
+
+ b.Property("Status")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("Projects");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.Model.UserState", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Cnpj")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("CommercialEmail")
+ .HasColumnType("TEXT");
+
+ b.Property("CreateAt")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("PersistenceId")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("BLOB");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.ReadModel.ProjectProjection", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Budget")
+ .HasColumnType("TEXT");
+
+ b.Property("ClientId")
+ .HasColumnType("TEXT");
+
+ b.Property("ClientName")
+ .HasColumnType("TEXT");
+
+ b.Property("Code")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("OrderNumber")
+ .HasColumnType("TEXT");
+
+ b.Property("Owner")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("INTEGER");
+
+ b.Property("StartDate")
+ .HasColumnType("TEXT");
+
+ b.Property("Status")
+ .HasColumnType("INTEGER");
+
+ b.Property("StatusName")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("ProjectsProjection");
+ });
+
+ modelBuilder.Entity("AppFabric.Persistence.ReadModel.UserProjection", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("TEXT");
+
+ b.Property("Cnpj")
+ .HasColumnType("TEXT");
+
+ b.Property("CommercialEmail")
+ .HasColumnType("TEXT");
+
+ b.Property("IsDeleted")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("RowVersion")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("UsersProjection");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Model/ActivityState.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Model/ActivityState.cs
new file mode 100644
index 0000000..2aa3c88
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Model/ActivityState.cs
@@ -0,0 +1,42 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using AppFabric.Persistence.Framework.Model;
+
+namespace AppFabric.Persistence.Model
+{
+ public class ActivityState : PersistentState
+ {
+ public ActivityState(int status, string description, uint activityId, uint projectId, byte[] rowVersion)
+ : base(DateTime.Now, rowVersion)
+ {
+ ActivityId = activityId;
+ Status = status;
+ Description = description;
+ ProjectId = projectId;
+ }
+
+ public uint ActivityId { get; set; }
+ public int Status { get; set; }
+ public string Description { get; set; }
+
+ public uint ProjectId { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Model/ClientState.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Model/ClientState.cs
new file mode 100644
index 0000000..c367e14
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Model/ClientState.cs
@@ -0,0 +1,37 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using AppFabric.Persistence.Framework.Model;
+
+namespace AppFabric.Persistence.Model
+{
+ public class ClientState : PersistentState
+ {
+ public ClientState(long projectId, long clientId, byte[] rowVersion)
+ :base(DateTime.Now,rowVersion)
+ {
+ ProjectId = projectId;
+ ClientId = clientId;
+ }
+
+ public long ProjectId { get; set;}
+ public long ClientId { get; set;}
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Model/ProjectState.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Model/ProjectState.cs
new file mode 100644
index 0000000..606a0ad
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Model/ProjectState.cs
@@ -0,0 +1,54 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using AppFabric.Persistence.Framework.Model;
+
+namespace AppFabric.Persistence.Model
+{
+ public class ProjectState : PersistentState
+ {
+ public ProjectState(Guid id, string name, string code, decimal budget, DateTime startDate, Guid clientId, string owner, string orderNumber, int status, byte[] rowVersion)
+ :base(startDate, rowVersion)
+ {
+ Id = id;
+ ClientId = clientId;
+ Name = name;
+ Code = code;
+ StartDate = startDate;
+ Budget = budget;
+ Owner = owner;
+ Status = status;
+ OrderNumber = orderNumber;
+ }
+
+ public Guid Id { get; set; }
+ public Guid ClientId { get; set;}
+ public string Name { get; set;}
+ public string Code { get; set;}
+ public DateTime StartDate { get; set;}
+ public decimal Budget { get; set;}
+
+ public string Owner { get; set;}
+
+ public string OrderNumber { get; set;}
+
+ public int Status { get; set;}
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/IProjectRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/IProjectRepository.cs
new file mode 100644
index 0000000..fd4b9b0
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/IProjectRepository.cs
@@ -0,0 +1,29 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using AppFabric.Domain.BusinessObjects;
+using AppFabric.Persistence.Framework.Repositories;
+
+namespace AppFabric.Persistence.Model.Repositories
+{
+ public interface IProjectRepository: IRepository
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/IUserRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/IUserRepository.cs
new file mode 100644
index 0000000..006ea53
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/IUserRepository.cs
@@ -0,0 +1,29 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using AppFabric.Domain.BusinessObjects;
+using AppFabric.Persistence.Framework.Repositories;
+
+namespace AppFabric.Persistence.Model.Repositories
+{
+ public interface IUserRepository: IRepository
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/ProjectRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/ProjectRepository.cs
new file mode 100644
index 0000000..58e4e18
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/ProjectRepository.cs
@@ -0,0 +1,104 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using Microsoft.EntityFrameworkCore;
+using AppFabric.Domain.BusinessObjects;
+using AppFabric.Domain.Framework.BusinessObjects;
+using AppFabric.Persistence.ExtensionMethods;
+using Version = AppFabric.Domain.BusinessObjects.Version;
+
+namespace AppFabric.Persistence.Model.Repositories
+{
+ public class ProjectRepository : IProjectRepository
+ {
+ public ProjectRepository(AppFabricDbContext context)
+ {
+ DbContext = context;
+ }
+
+ private AppFabricDbContext DbContext { get; }
+
+ // https://docs.microsoft.com/en-us/ef/core/saving/disconnected-entities
+
+ public void Add(Project entity)
+ {
+ var entry = entity.ToProjectState();
+ var oldState = DbContext.Projects
+ .OrderByDescending(ob => ob.Id)
+ .ThenByDescending(ob => ob.RowVersion)
+ .FirstOrDefault(t => t.Id == entity.Id.Value);
+
+ if (oldState == null)
+ {
+ DbContext.Projects.Add(entry);
+ }
+ else
+ {
+ var version = Version.From(BitConverter.ToInt32(oldState.RowVersion));
+
+ if (Version.Next(version) > entity.Version)
+ {
+ throw new DbUpdateConcurrencyException("This version is not the most updated for this object.");
+ }
+
+ DbContext.Entry(oldState).CurrentValues.SetValues(entry);
+ }
+ }
+
+ public void Remove(Project entity)
+ {
+ var oldState = Get(entity.Id);
+
+ if (Version.Next(oldState.Version) > entity.Version)
+ {
+ throw new DbUpdateConcurrencyException("This version is not the most updated for this object.");
+ }
+
+ var entry = entity.ToProjectState();
+
+ DbContext.Projects.Remove(entry);
+ }
+
+ public Project Get(EntityId id)
+ {
+ var project = DbContext.Projects.AsNoTracking()
+ .OrderByDescending(ob => ob.Id)
+ .ThenByDescending(ob => ob.RowVersion)
+ .FirstOrDefault(t => t.Id == id.Value);
+
+ if (project == null)
+ {
+ return Project.Empty();
+ }
+
+ return project.ToProject();
+ }
+
+ public IEnumerable Find(Expression> predicate)
+ {
+ return DbContext.Projects.Where(predicate).AsNoTracking()
+ .Select(t => t.ToProject());
+ ;
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/UserRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/UserRepository.cs
new file mode 100644
index 0000000..a10162a
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Model/Repositories/UserRepository.cs
@@ -0,0 +1,100 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using Microsoft.EntityFrameworkCore;
+using AppFabric.Domain.BusinessObjects;
+using AppFabric.Domain.Framework.BusinessObjects;
+using AppFabric.Persistence.ExtensionMethods;
+using Version = AppFabric.Domain.BusinessObjects.Version;
+
+namespace AppFabric.Persistence.Model.Repositories
+{
+ public class UserRepository : IUserRepository
+ {
+ public UserRepository(AppFabricDbContext context)
+ {
+ DbContext = context;
+ }
+
+ private AppFabricDbContext DbContext { get; }
+
+ // https://docs.microsoft.com/en-us/ef/core/saving/disconnected-entities
+
+ public void Add(User entity)
+ {
+ var entry = entity.ToUserState();
+
+ var oldState = Get(entity.Id);
+
+ if (oldState.Equals(User.Empty()))
+ {
+ DbContext.Users.Add(entry);
+ }
+ else
+ {
+ if (Version.Next(oldState.Version) > entity.Version)
+ {
+ throw new DbUpdateConcurrencyException("This version is not the most updated for this object.");
+ }
+
+ DbContext.Entry(oldState).CurrentValues.SetValues(entry);
+ }
+ }
+
+ public void Remove(User entity)
+ {
+ var oldState = Get(entity.Id);
+
+ if (Version.Next(oldState.Version) > entity.Version)
+ {
+ throw new DbUpdateConcurrencyException("This version is not the most updated for this object.");
+ }
+
+ var entry = entity.ToUserState();
+
+ DbContext.Users.Remove(entry);
+ }
+
+ public User Get(EntityId id)
+ {
+ var user = DbContext.Users.AsNoTracking()
+ .OrderByDescending(ob => ob.Id)
+ .ThenByDescending(ob => ob.RowVersion)
+ .FirstOrDefault(t =>t.Id.Equals(id.Value));
+
+ if (user == null)
+ {
+ return User.Empty();
+ }
+
+ return user.ToUser();
+ }
+
+ public IEnumerable Find(Expression> predicate)
+ {
+ return DbContext.Users.Where(predicate).AsNoTracking()
+ .Select(t => t.ToUser());
+ ;
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/Model/UserState.cs b/samples/DFlow.Samples.Persistence.EntityFramework/Model/UserState.cs
new file mode 100644
index 0000000..2df8fe7
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/Model/UserState.cs
@@ -0,0 +1,41 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using AppFabric.Persistence.Framework.Model;
+
+namespace AppFabric.Persistence.Model
+{
+ public class UserState : PersistentState
+ {
+ public UserState(Guid id, string name, string cnpj, string commercialEmail, byte[] rowVersion)
+ :base(DateTime.Now, rowVersion)
+ {
+ Id = id;
+ Name = name;
+ Cnpj = cnpj;
+ CommercialEmail = commercialEmail;
+ }
+
+ public Guid Id { get; set;}
+ public string Name { get; set;}
+ public string Cnpj { get; set;}
+ public string CommercialEmail { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/ActivityProjection.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/ActivityProjection.cs
new file mode 100644
index 0000000..4904fb5
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/ActivityProjection.cs
@@ -0,0 +1,49 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+
+namespace AppFabric.Persistence.ReadModel
+{
+ public class ActivityProjection
+ {
+ public ActivityProjection()
+ {
+ }
+ public ActivityProjection(string status, string description, Guid activityId, Guid projectId)
+ {
+ ActivityId = activityId;
+ Status = status;
+ Description = description;
+ ProjectId = projectId;
+ }
+
+ public Guid ActivityId { get; set; }
+ public string Status { get; set; }
+ public string Description { get; set; }
+ public Guid ProjectId { get; set; }
+
+
+ public static ActivityProjection Empty()
+ {
+ return new ActivityProjection(String.Empty, String.Empty, Guid.Empty, Guid.Empty);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/ProjectProjection.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/ProjectProjection.cs
new file mode 100644
index 0000000..789a4ad
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/ProjectProjection.cs
@@ -0,0 +1,68 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+
+namespace AppFabric.Persistence.ReadModel
+{
+ public class ProjectProjection
+ {
+ public ProjectProjection(Guid id, string name, string code, decimal budget, DateTime startDate, Guid clientId, string clientName, string owner, string orderNumber, int status, string statusName, int rowVersion)
+ {
+ Id = id;
+ ClientId = clientId;
+ ClientName = clientName;
+ Name = name;
+ Code = code;
+ StartDate = startDate;
+ Budget = budget;
+ Owner = owner;
+ Status = status;
+ StatusName = statusName;
+ OrderNumber = orderNumber;
+ IsDeleted = false;
+ RowVersion = rowVersion;
+ }
+
+ public Guid Id { get; set; }
+ public Guid ClientId { get; set; }
+ public string ClientName { get; set; }
+ public string Name { get; set; }
+ public string Code { get; set; }
+ public DateTime StartDate { get; set; }
+ public decimal Budget { get; set; }
+ public string Owner { get; set; }
+
+ public string OrderNumber { get; set; }
+
+ public int Status { get; set; }
+ public string StatusName { get; set; }
+
+ public bool IsDeleted { get; set; }
+
+ public int RowVersion { get; set; }
+
+ public static ProjectProjection Empty()
+ {
+ return new ProjectProjection(Guid.Empty, String.Empty, String.Empty, Decimal.Zero,
+ DateTime.UnixEpoch,Guid.Empty, String.Empty, String.Empty, String.Empty,
+ 0, String.Empty, 0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/ActivityProjectionRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/ActivityProjectionRepository.cs
new file mode 100644
index 0000000..a298129
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/ActivityProjectionRepository.cs
@@ -0,0 +1,58 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using Microsoft.EntityFrameworkCore;
+using AppFabric.Domain.Framework.BusinessObjects;
+using Version = AppFabric.Domain.BusinessObjects.Version;
+
+namespace AppFabric.Persistence.ReadModel.Repositories
+{
+ public sealed class ActivityProjectionRepository : IActivityProjectionRepository
+ {
+ private AppFabricDbContext Context { get; }
+ public ActivityProjectionRepository(AppFabricDbContext context)
+ {
+ Context = context;
+ }
+
+ public ActivityProjection Get(EntityId id)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Add(ActivityProjection entity)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Remove(ActivityProjection entity)
+ {
+ throw new NotImplementedException();
+ }
+
+ public IReadOnlyList Find(Expression> predicate)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/IActivityProjectionRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/IActivityProjectionRepository.cs
new file mode 100644
index 0000000..0fa526a
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/IActivityProjectionRepository.cs
@@ -0,0 +1,26 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+using AppFabric.Persistence.Framework.ReadModel.Repositories;
+
+namespace AppFabric.Persistence.ReadModel.Repositories
+{
+ public interface IActivityProjectionRepository : IProjectionRepository
+ {
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/IProjectProjectionRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/IProjectProjectionRepository.cs
new file mode 100644
index 0000000..093bc4b
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/IProjectProjectionRepository.cs
@@ -0,0 +1,27 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+using AppFabric.Persistence.Framework.ReadModel.Repositories;
+
+namespace AppFabric.Persistence.ReadModel.Repositories
+{
+ public interface IProjectProjectionRepository : IProjectionRepository
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/IUserProjectionRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/IUserProjectionRepository.cs
new file mode 100644
index 0000000..c236d88
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/IUserProjectionRepository.cs
@@ -0,0 +1,27 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+using AppFabric.Persistence.Framework.ReadModel.Repositories;
+
+namespace AppFabric.Persistence.ReadModel.Repositories
+{
+ public interface IUserProjectionRepository : IProjectionRepository
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/ProjectProjectionRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/ProjectProjectionRepository.cs
new file mode 100644
index 0000000..3a1179b
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/ProjectProjectionRepository.cs
@@ -0,0 +1,76 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using AppFabric.Domain.Framework.BusinessObjects;
+using Version = AppFabric.Domain.BusinessObjects.Version;
+
+namespace AppFabric.Persistence.ReadModel.Repositories
+{
+ public sealed class ProjectProjectionRepository : IProjectProjectionRepository
+ {
+ private readonly AppFabricDbContext _context;
+ public ProjectProjectionRepository(AppFabricDbContext context)
+ {
+ _context = context;
+ }
+
+ public ProjectProjection Get(EntityId id)
+ {
+ var project = _context.ProjectsProjection
+ .FirstOrDefault(ac => ac.Id.Equals(id.Value));
+
+ if (project == null)
+ {
+ ProjectProjection.Empty();
+ }
+
+ return project;
+ }
+
+ public void Add(ProjectProjection entity)
+ {
+ var oldState =
+ _context.ProjectsProjection
+ .FirstOrDefault(b => b.Id == entity.Id);
+
+ if (oldState == null)
+ {
+ _context.ProjectsProjection.Add(entity);
+ }
+ else
+ {
+ _context.Entry(oldState).CurrentValues.SetValues(entity);
+ }
+ }
+
+ public void Remove(ProjectProjection entity)
+ {
+ _context.ProjectsProjection.Remove(entity);
+ }
+
+ public IReadOnlyList Find(Expression> predicate)
+ {
+ return _context.ProjectsProjection.Where(predicate).ToList();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/UserProjectionRepository.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/UserProjectionRepository.cs
new file mode 100644
index 0000000..ddbc059
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/Repositories/UserProjectionRepository.cs
@@ -0,0 +1,81 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using AppFabric.Domain.Framework.BusinessObjects;
+using Version = AppFabric.Domain.BusinessObjects.Version;
+
+namespace AppFabric.Persistence.ReadModel.Repositories
+{
+ public sealed class UserProjectionRepository : IUserProjectionRepository
+ {
+ private readonly AppFabricDbContext _context;
+ public UserProjectionRepository(AppFabricDbContext context)
+ {
+ _context = context;
+ }
+
+ public UserProjection Get(EntityId id)
+ {
+ var user = _context.UsersProjection
+ .FirstOrDefault(ac => ac.Id.Equals(id.Value));
+
+ if (user == null)
+ {
+ UserProjection.Empty();
+ }
+
+ return user;
+ }
+
+ public void Add(UserProjection entity)
+ {
+ var oldState =
+ _context.UsersProjection.FirstOrDefault(b => b.Id == entity.Id);
+
+ if (oldState == null)
+ {
+ _context.UsersProjection.Add(entity);
+ }
+ else
+ {
+ _context.Entry(oldState).CurrentValues.SetValues(entity);
+ }
+ }
+
+ public void Remove(UserProjection entity)
+ {
+ var oldState =
+ _context.UsersProjection
+ .OrderByDescending(or => or.RowVersion)
+ .FirstOrDefault(b => b.Id.Equals(entity.Id) &&
+ b.RowVersion.Equals(entity.RowVersion));
+
+ _context.UsersProjection.Remove(entity);
+ }
+
+ public IReadOnlyList Find(Expression> predicate)
+ {
+ return _context.UsersProjection.Where(predicate).ToList();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/UserProjection.cs b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/UserProjection.cs
new file mode 100644
index 0000000..c617fbe
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/ReadModel/UserProjection.cs
@@ -0,0 +1,53 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using System;
+
+namespace AppFabric.Persistence.ReadModel
+{
+ public class UserProjection
+ {
+ public UserProjection()
+ {
+ }
+ public UserProjection(Guid id, string name, string cnpj, string commercialEmail, int rowVersion)
+ {
+ Id = id;
+ Name = name;
+ Cnpj = cnpj;
+ CommercialEmail = commercialEmail;
+ IsDeleted = false;
+ RowVersion = rowVersion;
+ }
+
+ public Guid Id { get; set; }
+ public string Name { get; set; }
+ public string Cnpj { get; set; }
+ public string CommercialEmail { get; set; }
+
+ public bool IsDeleted { get; set; }
+
+ public int RowVersion { get; set; }
+
+ public static UserProjection Empty()
+ {
+ return new UserProjection(Guid.Empty, String.Empty, String.Empty, String.Empty,0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/AddedProjectProjectionHandler.cs b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/AddedProjectProjectionHandler.cs
new file mode 100644
index 0000000..fe88a0a
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/AddedProjectProjectionHandler.cs
@@ -0,0 +1,62 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using AppFabric.Domain.AggregationProject.Events;
+using AppFabric.Domain.Framework.DomainEvents;
+using AppFabric.Persistence.Framework;
+using AppFabric.Persistence.ReadModel;
+using AppFabric.Persistence.ReadModel.Repositories;
+
+namespace AppFabric.Persistence.SyncModels.DomainEventHandlers
+{
+ public sealed class AddedProjectProjectionHandler : DomainEventHandler
+ {
+ private readonly IDbSession _projectSession;
+ private readonly IDbSession _userSession;
+
+ public AddedProjectProjectionHandler(IDbSession projectSession,
+ IDbSession userSession)
+ {
+ _projectSession = projectSession;
+ _userSession = userSession;
+ }
+
+ protected override void ExecuteHandle(ProjectAddedEvent @event)
+ {
+ var client = _userSession.Repository.Get(@event.ClientId);
+
+ var projection = new ProjectProjection(
+ @event.Id.Value,
+ @event.Name.Value,
+ @event.Code.Value,
+ @event.Budget.Value,
+ @event.StartDate.Value,
+ @event.ClientId.Value,
+ client.Name,
+ @event.Owner.Value,
+ @event.OrderNumber.Value,
+ @event.Status.Value,
+ @event.Status.ToString(),
+ @event.Version.Value);
+
+ _projectSession.Repository.Add(projection);
+ _projectSession.SaveChanges();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/AddedUserProjectionHandler.cs b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/AddedUserProjectionHandler.cs
new file mode 100644
index 0000000..552d213
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/AddedUserProjectionHandler.cs
@@ -0,0 +1,51 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using AppFabric.Domain.AggregationProject.Events;
+using AppFabric.Domain.AggregationUser.Events;
+using AppFabric.Domain.Framework.DomainEvents;
+using AppFabric.Persistence.Framework;
+using AppFabric.Persistence.ReadModel;
+using AppFabric.Persistence.ReadModel.Repositories;
+
+namespace AppFabric.Persistence.SyncModels.DomainEventHandlers
+{
+ public sealed class AddedUserProjectionHandler : DomainEventHandler
+ {
+ private readonly IDbSession _projectSession;
+
+ public AddedUserProjectionHandler(IDbSession projectSession)
+ {
+ _projectSession = projectSession;
+ }
+
+ protected override void ExecuteHandle(UserAddedEvent @event)
+ {
+ var projection = new UserProjection(
+ @event.Id.Value,
+ @event.Name.Value,
+ @event.Cnpj.Value,
+ @event.CommercialEmail.Value,
+ @event.Version.Value);
+
+ _projectSession.Repository.Add(projection);
+ _projectSession.SaveChanges();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/RemoveProjectProjectionHandler.cs b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/RemoveProjectProjectionHandler.cs
new file mode 100644
index 0000000..2283fb8
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/RemoveProjectProjectionHandler.cs
@@ -0,0 +1,45 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using AppFabric.Domain.AggregationProject.Events;
+using AppFabric.Domain.Framework.DomainEvents;
+using AppFabric.Persistence.Framework;
+using AppFabric.Persistence.ReadModel.Repositories;
+
+namespace AppFabric.Persistence.SyncModels.DomainEventHandlers
+{
+ public sealed class RemoveProjectProjectionHandler : DomainEventHandler
+ {
+ private readonly IDbSession _projectSession;
+
+ public RemoveProjectProjectionHandler(IDbSession projectSession)
+ {
+ _projectSession = projectSession;
+ }
+
+ protected override void ExecuteHandle(ProjectRemovedEvent @event)
+ {
+ var project = _projectSession.Repository.Get(@event.Id);
+
+ _projectSession.Repository.Remove(project);
+
+ _projectSession.SaveChanges();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/RemoveUserProjectionHandler.cs b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/RemoveUserProjectionHandler.cs
new file mode 100644
index 0000000..fdbc8f5
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/RemoveUserProjectionHandler.cs
@@ -0,0 +1,45 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using AppFabric.Domain.AggregationProject.Events;
+using AppFabric.Domain.Framework.DomainEvents;
+using AppFabric.Persistence.Framework;
+using AppFabric.Persistence.ReadModel.Repositories;
+
+namespace AppFabric.Persistence.SyncModels.DomainEventHandlers
+{
+ public sealed class RemoveUserProjectionHandler : DomainEventHandler
+ {
+ private readonly IDbSession _userSession;
+
+ public RemoveUserProjectionHandler(IDbSession userSession)
+ {
+ _userSession = userSession;
+ }
+
+ protected override void ExecuteHandle(UserRemovedEvent @event)
+ {
+ var user = _userSession.Repository.Get(@event.Id);
+
+ _userSession.Repository.Remove(user);
+
+ _userSession.SaveChanges();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/UpdateProjectDetailsProjectionHandler.cs b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/UpdateProjectDetailsProjectionHandler.cs
new file mode 100644
index 0000000..c6e36ac
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/SyncModels/DomainEventHandlers/UpdateProjectDetailsProjectionHandler.cs
@@ -0,0 +1,59 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU Library General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+//
+
+
+using AppFabric.Domain.AggregationProject.Events;
+using AppFabric.Domain.Framework.DomainEvents;
+using AppFabric.Persistence.Framework;
+using AppFabric.Persistence.ReadModel;
+using AppFabric.Persistence.ReadModel.Repositories;
+
+namespace AppFabric.Persistence.SyncModels.DomainEventHandlers
+{
+ public class UpdateProjectDetailsProjectionHandler : DomainEventHandler
+ {
+ private readonly IDbSession _projectSession;
+
+ public UpdateProjectDetailsProjectionHandler(IDbSession projectSession)
+ {
+ _projectSession = projectSession;
+ }
+
+ protected override void ExecuteHandle(ProjectDetailUpdatedEvent @event)
+ {
+ var project = _projectSession.Repository.Get(@event.Id);
+
+ var projection = new ProjectProjection(
+ project.Id,
+ @event.Name.Value,
+ project.Code,
+ @event.Budget.Value,
+ project.StartDate,
+ project.ClientId,
+ project.ClientName,
+ @event.Owner.Value,
+ @event.OrderNumber.Value,
+ project.Status,
+ project.StatusName,
+ @event.Version.Value);
+
+ _projectSession.Repository.Add(projection);
+ _projectSession.SaveChanges();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples.Persistence.EntityFramework/TodoAgilityDbContext.cs b/samples/DFlow.Samples.Persistence.EntityFramework/TodoAgilityDbContext.cs
new file mode 100644
index 0000000..1f63908
--- /dev/null
+++ b/samples/DFlow.Samples.Persistence.EntityFramework/TodoAgilityDbContext.cs
@@ -0,0 +1,96 @@
+using Microsoft.EntityFrameworkCore;
+using AppFabric.Persistence.Framework.Model;
+using AppFabric.Persistence.Model;
+using AppFabric.Persistence.ReadModel;
+
+namespace AppFabric.Persistence
+{
+ public class AppFabricDbContext : AggregateDbContext
+ {
+ public AppFabricDbContext(DbContextOptions options)
+ : base(options)
+ {
+
+ }
+
+ public DbSet Projects { get; set; }
+ public DbSet ProjectsProjection { get; set; }
+ public DbSet Users { get; set; }
+ public DbSet UsersProjection { get; set; }
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+
+ modelBuilder.Entity(
+ b =>
+ {
+ b.Property(e => e.Id).ValueGeneratedNever().IsRequired();
+ b.Property(e => e.Code).IsRequired();
+ b.Property(e => e.Name).IsRequired();
+ b.Property(e => e.Budget).IsRequired();
+ b.HasKey(e => e.Id);
+ b.Property(e => e.ClientId).IsRequired();
+ b.Property(e => e.StartDate).IsRequired();
+
+ b.Property(p => p.PersistenceId);
+ b.Property(q => q.IsDeleted);
+ b.HasQueryFilter(project => EF.Property(project, "IsDeleted") == false);
+ b.Property(e => e.CreateAt);
+ b.Property(e => e.RowVersion);
+ });
+
+ modelBuilder.Entity(
+ b =>
+ {
+ b.Property(e => e.Id).ValueGeneratedNever().IsRequired();
+ b.Property(e => e.Name).IsRequired();
+ b.Property(e => e.Cnpj).IsRequired();
+
+ b.Property(p => p.PersistenceId);
+ b.Property(e => e.IsDeleted);
+ b.HasQueryFilter(user => EF.Property(user, "IsDeleted") == false);
+ b.Property(e => e.CreateAt);
+ b.Property(e => e.RowVersion);
+ });
+
+ modelBuilder.Entity(
+ b =>
+ {
+ b.Property(e => e.ProjectId).ValueGeneratedNever();
+ b.Property(e => e.ClientId).IsRequired();
+ b.HasKey(e => e.ClientId);
+ b.Property(p => p.PersistenceId);
+ b.Property(q => q.IsDeleted);
+ b.HasQueryFilter(client => EF.Property(client, "IsDeleted") == false);
+ b.Property(e => e.CreateAt);
+ b.Property(e => e.RowVersion);
+ });
+
+ #region projection
+
+ modelBuilder.Entity(p =>
+ {
+ p.Property(pr => pr.Id).ValueGeneratedNever();
+ p.HasKey(pr => pr.Id);
+ p.Property(pr => pr.Name);
+ p.Property(pr => pr.Code);
+ p.Property(pr => pr.StartDate);
+ p.Property(pr => pr.Budget);
+ p.Property(pr => pr.ClientId);
+ p.HasQueryFilter(proj => EF.Property(proj, "IsDeleted") == false);
+ });
+
+ modelBuilder.Entity(u =>
+ {
+ u.Property(pr => pr.Id).ValueGeneratedNever();
+ u.HasKey(pr => pr.Id);
+ u.Property(pr => pr.Name);
+ u.Property(pr => pr.Cnpj);
+ u.Property(pr => pr.CommercialEmail);
+ u.HasQueryFilter(user => EF.Property(user, "IsDeleted") == false);
+ });
+
+ #endregion
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Business/CommandHandlers/AddUserCommand.cs b/samples/DFlow.Samples/Business/CommandHandlers/AddUserCommand.cs
new file mode 100644
index 0000000..26e9cab
--- /dev/null
+++ b/samples/DFlow.Samples/Business/CommandHandlers/AddUserCommand.cs
@@ -0,0 +1,21 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using DFlow.Samples.BusinessObjects.Domain.BusinessObjects;
+
+namespace DFlow.Samples.Business.CommandHandlers
+{
+ public class AddUserCommand
+ {
+ public AddUserCommand(string name, string email)
+ {
+ Name = Name.From(name);
+ Mail = Email.From(email);
+ }
+ public Name Name { get; set; }
+ public Email Mail { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Business/CommandHandlers/AddUserCommandHandler.cs b/samples/DFlow.Samples/Business/CommandHandlers/AddUserCommandHandler.cs
new file mode 100644
index 0000000..75507d9
--- /dev/null
+++ b/samples/DFlow.Samples/Business/CommandHandlers/AddUserCommandHandler.cs
@@ -0,0 +1,44 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+
+using System;
+using System.Collections.Immutable;
+using DFlow.Business.Cqrs;
+using DFlow.Business.Cqrs.CommandHandlers;
+using DFlow.Domain.Events;
+using DFlow.Persistence;
+using DFlow.Samples.Domain.Aggregates;
+using DFlow.Samples.Persistence.Model.Repositories;
+
+namespace DFlow.Samples.Business.CommandHandlers
+{
+ public sealed class AddUserCommandHandler : CommandHandler>
+ {
+ public AddUserCommandHandler(IDomainEventBus publisher)
+ :base(publisher)
+ {
+ }
+
+ protected override CommandResult ExecuteCommand(AddUserCommand command)
+ {
+ var agg = UserEntityBasedAggregationRoot.CreateFrom(command.Name,command.Mail);
+
+ var isSucceed = agg.ValidationResults.IsValid;
+ var okId = Guid.Empty;
+
+ if (agg.ValidationResults.IsValid)
+ {
+ agg.GetEvents().ToImmutableList()
+ .ForEach( ev => Publisher.Publish(ev));
+
+ okId = agg.GetChange().Id.Value;
+ }
+
+ return new CommandResult(isSucceed, okId,agg.ValidationResults.Errors.ToImmutableList());
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Business/CommandHandlers/AddUserPersistentCommandHandler.cs b/samples/DFlow.Samples/Business/CommandHandlers/AddUserPersistentCommandHandler.cs
new file mode 100644
index 0000000..18030b6
--- /dev/null
+++ b/samples/DFlow.Samples/Business/CommandHandlers/AddUserPersistentCommandHandler.cs
@@ -0,0 +1,49 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+
+using System;
+using System.Collections.Immutable;
+using DFlow.Business.Cqrs;
+using DFlow.Business.Cqrs.CommandHandlers;
+using DFlow.Domain.Events;
+using DFlow.Persistence;
+using DFlow.Samples.Domain.Aggregates;
+using DFlow.Samples.Persistence.Model.Repositories;
+
+namespace DFlow.Samples.Business.CommandHandlers
+{
+ public sealed class AddUserPersistentCommandHandler : CommandHandler>
+ {
+ private readonly IDbSession _sessionDb;
+ public AddUserPersistentCommandHandler(IDomainEventBus publisher, IDbSession sessionDb)
+ :base(publisher)
+ {
+ _sessionDb = sessionDb;
+ }
+
+ protected override CommandResult ExecuteCommand(AddUserCommand command)
+ {
+ var agg = UserEntityBasedAggregationRoot.CreateFrom(command.Name,command.Mail);
+
+ var isSucceed = agg.ValidationResults.IsValid;
+ var okId = Guid.Empty;
+
+ if (agg.ValidationResults.IsValid)
+ {
+ _sessionDb.Repository.Add(agg.GetChange());
+ _sessionDb.SaveChanges();
+
+ agg.GetEvents().ToImmutableList()
+ .ForEach( ev => Publisher.Publish(ev));
+
+ okId = agg.GetChange().Id.Value;
+ }
+
+ return new CommandResult(isSucceed, okId,agg.ValidationResults.Errors.ToImmutableList());
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Business/DomainEventHandlers/UserAddedDomainEventHandler.cs b/samples/DFlow.Samples/Business/DomainEventHandlers/UserAddedDomainEventHandler.cs
new file mode 100644
index 0000000..c8b946f
--- /dev/null
+++ b/samples/DFlow.Samples/Business/DomainEventHandlers/UserAddedDomainEventHandler.cs
@@ -0,0 +1,20 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using System;
+using DFlow.Domain.Events;
+using DFlow.Samples.Domain.Aggregates.Events;
+
+namespace DFlow.Samples.Business.DomainEventHandlers
+{
+ public sealed class UserAddedDomainEventHandler : DomainEventHandler
+ {
+ protected override void ExecuteHandle(UserAddedEvent @event)
+ {
+ Console.WriteLine($"[{nameof(UserAddedEvent)}] event: {@event.Id}: name: {@event.Name} date: {@event.When}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Business/DomainEventHandlers/UserAddedUpdateProjectionDomainEventHandler.cs b/samples/DFlow.Samples/Business/DomainEventHandlers/UserAddedUpdateProjectionDomainEventHandler.cs
new file mode 100644
index 0000000..56cf8eb
--- /dev/null
+++ b/samples/DFlow.Samples/Business/DomainEventHandlers/UserAddedUpdateProjectionDomainEventHandler.cs
@@ -0,0 +1,29 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using DFlow.Domain.Events;
+using DFlow.Persistence;
+using DFlow.Samples.Domain.Aggregates.Events;
+using DFlow.Samples.Persistence.ReadModel;
+using DFlow.Samples.Persistence.ReadModel.Repositories;
+
+namespace DFlow.Samples.Business.DomainEventHandlers
+{
+ public sealed class UserAddedUpdateProjectionDomainEventHandler : DomainEventHandler
+ {
+ private IDbSession _dbSession;
+ public UserAddedUpdateProjectionDomainEventHandler(IDbSession dbSession)
+ {
+ _dbSession = dbSession;
+ }
+ protected override void ExecuteHandle(UserAddedEvent @event)
+ {
+ _dbSession.Repository.Add(new UserProjection(@event.Id.Value, @event.Name.Value,
+ @event.Mail.Value, @event.Version.Value));
+ _dbSession.SaveChanges();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Business/QueryHandlers/GetUsersByFilter.cs b/samples/DFlow.Samples/Business/QueryHandlers/GetUsersByFilter.cs
new file mode 100644
index 0000000..a35a05c
--- /dev/null
+++ b/samples/DFlow.Samples/Business/QueryHandlers/GetUsersByFilter.cs
@@ -0,0 +1,28 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+namespace DFlow.Samples.Business.QueryHandlers
+{
+ public class GetUsersByFilter
+ {
+ private GetUsersByFilter(string name)
+ {
+ Name = name;
+ }
+
+ public string Name { get; }
+
+ public static GetUsersByFilter From(string name)
+ {
+ if (string.IsNullOrEmpty(name))
+ {
+ name = string.Empty;
+ }
+
+ return new GetUsersByFilter(name);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Business/QueryHandlers/GetUsersByQueryHandler.cs b/samples/DFlow.Samples/Business/QueryHandlers/GetUsersByQueryHandler.cs
new file mode 100644
index 0000000..616eb80
--- /dev/null
+++ b/samples/DFlow.Samples/Business/QueryHandlers/GetUsersByQueryHandler.cs
@@ -0,0 +1,30 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using DFlow.Business.Cqrs;
+using DFlow.Persistence;
+using DFlow.Samples.Persistence.ReadModel.Repositories;
+
+namespace DFlow.Samples.Business.QueryHandlers
+{
+ public sealed class GetUsersByQueryHandler : QueryHandler
+ {
+ private readonly IDbSession _dbSession;
+
+ public GetUsersByQueryHandler(IDbSession session)
+ {
+ _dbSession = session;
+ }
+
+ protected override GetUsersResponse ExecuteQuery(GetUsersByFilter filter)
+ {
+ var clients = _dbSession.Repository
+ .Find(up=> up.Name.Contains(filter.Name));
+
+ return GetUsersResponse.From(clients.Count>0, clients);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Business/QueryHandlers/GetUsersResponse.cs b/samples/DFlow.Samples/Business/QueryHandlers/GetUsersResponse.cs
new file mode 100644
index 0000000..d62f739
--- /dev/null
+++ b/samples/DFlow.Samples/Business/QueryHandlers/GetUsersResponse.cs
@@ -0,0 +1,25 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using System.Collections.Generic;
+using DFlow.Business.Cqrs.QueryHandlers;
+using DFlow.Samples.Persistence.ReadModel;
+
+namespace DFlow.Samples.Business.QueryHandlers
+{
+ public class GetUsersResponse:QueryResult>
+ {
+ public GetUsersResponse(bool isSucceed, IReadOnlyList data)
+ :base(isSucceed, data)
+ {
+ }
+
+ public static GetUsersResponse From(bool isSucceed, IReadOnlyList items)
+ {
+ return new GetUsersResponse(isSucceed,items);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/DFlow.Samples.csproj b/samples/DFlow.Samples/DFlow.Samples.csproj
new file mode 100644
index 0000000..62ca49a
--- /dev/null
+++ b/samples/DFlow.Samples/DFlow.Samples.csproj
@@ -0,0 +1,29 @@
+
+
+
+ netcoreapp3.1
+ Debug;Release;Release Profilling
+ AnyCPU
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/DFlow.Samples/Domain/Aggregates/Events/UserAddedEvent.cs b/samples/DFlow.Samples/Domain/Aggregates/Events/UserAddedEvent.cs
new file mode 100644
index 0000000..1ae17d1
--- /dev/null
+++ b/samples/DFlow.Samples/Domain/Aggregates/Events/UserAddedEvent.cs
@@ -0,0 +1,36 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+
+using System;
+using DFlow.Domain.DomainEvents;
+using DFlow.Samples.BusinessObjects.Domain.BusinessObjects;
+using DFlow.Samples.Domain.BusinessObjects;
+using Version = DFlow.Domain.BusinessObjects.Version;
+
+namespace DFlow.Samples.Domain.Aggregates.Events
+{
+ public class UserAddedEvent : DomainEvent
+ {
+ private UserAddedEvent(EntityId clientId, Name name, Email mail, Version version)
+ : base(DateTime.Now, version)
+ {
+ Id = clientId;
+ Name = name;
+ Mail = mail;
+ }
+ public EntityId Id { get; }
+
+ public Name Name { get; }
+
+ public Email Mail { get; }
+
+ public static UserAddedEvent For(User user)
+ {
+ return new UserAddedEvent(user.Id,user.Name,user.Mail, user.Version);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Domain/Aggregates/UserEntityBasedAggregationRoot.cs b/samples/DFlow.Samples/Domain/Aggregates/UserEntityBasedAggregationRoot.cs
new file mode 100644
index 0000000..180621c
--- /dev/null
+++ b/samples/DFlow.Samples/Domain/Aggregates/UserEntityBasedAggregationRoot.cs
@@ -0,0 +1,43 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using DFlow.Domain.Aggregates;
+using DFlow.Domain.BusinessObjects;
+using DFlow.Samples.BusinessObjects.Domain.BusinessObjects;
+using DFlow.Samples.Domain.Aggregates.Events;
+using DFlow.Samples.Domain.BusinessObjects;
+
+namespace DFlow.Samples.Domain.Aggregates
+{
+ public sealed class UserEntityBasedAggregationRoot : ObjectBasedAggregationRoot
+ {
+
+ private UserEntityBasedAggregationRoot(User user)
+ {
+ if (user.ValidationResults.IsValid)
+ {
+ Apply(user);
+
+ if (user.IsNew())
+ {
+ Raise(UserAddedEvent.For(user));
+ }
+ }
+
+ ValidationResults = user.ValidationResults;
+ }
+
+ #region Aggregation contruction
+
+ public static UserEntityBasedAggregationRoot CreateFrom(Name name, Email commercialEmail)
+ {
+ var user = User.From(EntityId.GetNext(), name, commercialEmail, Version.New());
+ return new UserEntityBasedAggregationRoot(user);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Domain/Aggregates/UserObjectBasedAggregationRootWithEvent.cs b/samples/DFlow.Samples/Domain/Aggregates/UserObjectBasedAggregationRootWithEvent.cs
new file mode 100644
index 0000000..7c3aba5
--- /dev/null
+++ b/samples/DFlow.Samples/Domain/Aggregates/UserObjectBasedAggregationRootWithEvent.cs
@@ -0,0 +1,37 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using DFlow.Domain.Aggregates;
+using DFlow.Domain.BusinessObjects;
+using DFlow.Samples.BusinessObjects.Domain.BusinessObjects;
+using DFlow.Samples.Domain.BusinessObjects;
+
+namespace DFlow.Samples.Domain.Aggregates
+{
+ public sealed class UserObjectBasedAggregationRootWithEvent : ObjectBasedAggregationRoot
+ {
+
+ private UserObjectBasedAggregationRootWithEvent(User user)
+ {
+ if (user.ValidationResults.IsValid)
+ {
+ Apply(user);
+ }
+
+ ValidationResults = user.ValidationResults;
+ }
+
+ #region Aggregation contruction
+
+ public static UserObjectBasedAggregationRootWithEvent CreateFrom(Name name, Email commercialEmail)
+ {
+ var user = User.From(EntityId.GetNext(), name, commercialEmail, Version.New());
+ return new UserObjectBasedAggregationRootWithEvent(user);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Domain/Aggregates/UserObjectBasedAggregationRootWithoutEvent.cs b/samples/DFlow.Samples/Domain/Aggregates/UserObjectBasedAggregationRootWithoutEvent.cs
new file mode 100644
index 0000000..2fb8124
--- /dev/null
+++ b/samples/DFlow.Samples/Domain/Aggregates/UserObjectBasedAggregationRootWithoutEvent.cs
@@ -0,0 +1,37 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using DFlow.Domain.Aggregates;
+using DFlow.Domain.BusinessObjects;
+using DFlow.Samples.BusinessObjects.Domain.BusinessObjects;
+using DFlow.Samples.Domain.BusinessObjects;
+
+namespace DFlow.Samples.Domain.Aggregates
+{
+ public sealed class UserObjectBasedAggregationRootWithoutEvent : ObjectBasedAggregationRoot
+ {
+
+ private UserObjectBasedAggregationRootWithoutEvent(User user)
+ {
+ if (user.ValidationResults.IsValid)
+ {
+ Apply(user);
+ }
+
+ ValidationResults = user.ValidationResults;
+ }
+
+ #region Aggregation contruction
+
+ public static UserObjectBasedAggregationRootWithoutEvent CreateFrom(Name name, Email commercialEmail)
+ {
+ var user = User.From(EntityId.GetNext(), name, commercialEmail, Version.New());
+ return new UserObjectBasedAggregationRootWithoutEvent(user);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/samples/DFlow.Samples/Domain/BusinessObjects/Email.cs b/samples/DFlow.Samples/Domain/BusinessObjects/Email.cs
new file mode 100644
index 0000000..19f7be2
--- /dev/null
+++ b/samples/DFlow.Samples/Domain/BusinessObjects/Email.cs
@@ -0,0 +1,51 @@
+// Copyright (C) 2020 Road to Agility
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+using System;
+using System.Collections.Generic;
+using DFlow.Domain.Validation;
+using DFlow.Samples.BusinessObjects.Domain.BusinessObjects.Validations;
+
+namespace DFlow.Samples.BusinessObjects.Domain.BusinessObjects
+{
+ public sealed class Email : ValidationStatus
+ {
+ public string Value { get; }
+
+ private Email(string name)
+ {
+ Value = name;
+ }
+
+ public static Email From(string name)
+ {
+ var email = new Email(name);
+ var validator = new EmailValidator();
+
+ email.SetValidationResult(validator.Validate(email));
+
+ return email;
+ }
+
+ public static Email Empty()
+ {
+ return new Email(String.Empty);
+ }
+
+ public override string ToString()
+ {
+ return $"{Value}";
+ }
+
+ #region IEquatable
+
+ protected override IEnumerable