Hey, it's Georgii here 👋
Meet an enterprise software developer faced a lot of mature systems
successfully competing in the market. Sounds too good? 😏 Unless
bringing numbers of greenfield projects you'd surely face consequences
of that "success" 🙈 When it comes to "what took you so long?".
Here is a half decade pursued and finally embodied solution to the
problem of degrading development performance. It's tied up with
canonical production ready approaches for typical enterprise software
components. You'll find reasoning to your own framework ownerhip at a
complexity level you decide.
⚠️ WIP warning ⚠️
There's lack of some modules and examples that are to be implemented
in the near future. Hopefully the published work will hint you what to
expect next and decide whether to go deeper. Here are some TODOs:
| 1. Example per commit | ... covering implemented modules |
| 2. Modular split table | YourCompany.OLTP.RecordsManagement.DI.TransactionalComposition.EFCore |
| 3. Events with native broker client | YourCompany.OLTP.StateOwnership.EventsProducing.RabbitMQ |
| 4. The outbox | YourCompany.OLTP.StateOwnership.EventsProducing.RabbitMQ.EFCore |
| 5. Events processing | YourCompany.OLTP.RecordsManagement.DI.RabbitMQ |
| 6. Cross-cutting processing | YourCompany.OLTP.RecordsManagement.DI.TransactionalComposition.RabbitMQ |
| 7. Auto-generated full fledged REST API | YourCompany.OLTP.RecordsManagement.AspNet |
| 8. To be continued | ... other reusable modules |
- Comprehensive educational material for beginners (or your "Agents")
focused on bringing "human-understandable" business value rather than
the-faster-and-more-code-the-better. - Exhaustive open-source boilerplate covering all typical needs of
enterprise development properly put together for easy adoption to your
ownership at the entry point of choice. - Shift the industry and protect the mass of projects from mistakes
leading 9 of 10 to unmaintainable state after 3 years developming
inDeadline-Driven-Development environment(DDD 🤣🤣🤣)...
no matter architectural choices of its time. - Bring personally gained experience in a form that is too complex to
achieve while in rush on those 9 of 10.
The most important one 🤔 As practice shows, the amount is the main
performance killer 💀 (esp. by duplicating and glue-code bloating 💩).
The rule is The less code doing the job, the more value it brings.
Each piece you find here is evaluated with this metric.
Get-ChildItem -Exclude examples |
Get-ChildItem -Recurse -Filter '*.cs' -File |
Where-Object { $_.FullName -match '^(?:(?!examples\\).)*src\\YourCompany(?:(?!\\obj\\|\\bin\\).)+$' } |
ForEach-Object {
$measured = [System.IO.File]::ReadAllText($_.FullName, [System.Text.Encoding]::UTF8) | Measure-Object -Line;
[PSCustomObject]@{ Folder = $_.FullName; LineCount = $measured.Lines };
} |
Measure-Object -Property LineCount -SumWouldn't wish anyone an AI to assist one reaching the unmaintainable
human-incomprehensible amount of code as fast as six months rather
in those 3 years originally.
The main branch is "public" with commits of two types in its "trunk":
- commit --fixup
these are used whenever any change is intended for the latest version.
The fixups are always on top of the whole "entry point" branch graph
where more complex entry points include less complex ending up into
a holistic single solution (ie. the single merge commit into public).at least one of the fixups must change the root commit for
proper visualiation of the rebase resulting graph. - rebase -i --autosquash --rebase-merges --update-refs
following fixup rules this command copies the whole solution
while retaining the entry point branches structure. The resulting
graph's top commit always remain "merged to the trunk".
This way you'll never lose the entry point you had chosen when
cloned or submoduled this repo. And with versioning rules below
all the versions stay visualized with all the past fixups applied.
In other words the structure is consistent and immutable.
If used in your project code this approach acts as an extension to
Trunk Based Development.
Precisely the trunk is formed up with the fixups only while the roots
are updated at the end of iteration making your git history to be
self-documented and clean. Find more in ChatGPT generated article:
Two‑level rebase architectural narrative and evolution of the OLTP model.
⚠️ WIP warning ⚠️
From time to time you may fetch specially prefixed wip- branches.
Those aren't entry point branches yet so they won't be as safe and
consistent to use as the already finished ones (reachable from public).
Please be careful relying on them but the same time don't miss the
opportunity to look a little further and meet those coming soon
modules covering the extended needs you may demanded so long or
couldn't even imagine!
The main form of documenting is commit bodyes' description.
The commits within an entry point branch may be additionally
split by different authors. Authors are your teammates:
- 🏠 Domainman - demands tools to speak business over the code
while delegating its implementation. Forms up the framework you own.One remains an expert regardless the stack or even the
programming language and develops domain modules. - 🧱 Facademan - puts the domain modules together with tools like
ASP.NET, OpenAPI, Configuration, Reflection, Serialization, DI.
Exposes APIs, forms up supported API client stacks.One possesses best knowledge of the chosen entry point and
organizes its further development. - 💾 Persistman - speaks database over the code (not the one
restoring from backups, wish you'd never know it 😅).
Irreplaceble when it comes to EFCore or other persistence tools.One adopts, optimizes, upgrades database accessing modules
(unless being constantly distracted by Domainman 🙈). - 📦 Streamman - let it be either a broker's native client
library or a complex proxying framework like MassTransit or just
bare queue-table outbox - will depend on Domainman needs.One organizes data delivery and analysis, from
cross-cutting concerns, logging, short-circuiting, scheduling
to implementing specific data analysing domain services.
Likewise, each entry point's example project is accompanied with
README.md referenced in Entry points section below.
ℹ️ Studying advise
Make use of the editor's per-line git blaming abilities from
extensions like eamodio.gitlens. This helps a lot to grasp reasoning
behind an arbitrary line you're curently looking at at the right moment.
🎁 Bonus
You may find interesting to look at the last rebase todo list.
It is divided into Startup Iterations where your teammates work
together to build up the framework and then switch into their
dedicated fields. Btw, exactly those iteration numbers you can
see in the very beginning of the authored commits (1|, 2|, 3| ...).
Btw, updating this one for each version helps following the
branching rule of fixups to always contain one for the root commit 😉.
This is a boilerplate repo with consistent solution structure where
each subsequent fixup serie results in a new version of the
"entry point" branch graph.
In addition to current version's entry point branches there are
similarly named version-numbered tags. You can find it useful for
documenting purposes, using them for stable links in your documenation
letting to navigate to and browse your entry point online.
Though only the current version's "public-N" tag can be moved, once
another approved fixups' PR is rebased or squashed into the "public".
This way the boilerplate becomes safe for using in any form, from
simple submoduling to advanced hosting in your enterprise repo.
Motivation of this strategy is simple:
If you treat your "business-logic" valuable - you're interested in
owning the framework rather than "renting" it evenually.
This is a graph of the current entry point's solution aligned with
the Startup Iterations
(more in the last rebase todo list).
The top most commit is the most recent one tagged in the graph with
the last entry point branch included by your current revision.
All the entry point branches' heads are highlighted in the graph as ⏹️.
See the detailed commit descriptions gathered in Commit logs section.
---
config:
gitGraph:
mainBranchName: "7|🧱: OLTP DI EFCore integrated"
parallelCommits: true
rotateCommitLabel: false
showCommitLabel: false
---
gitGraph
%% commit type:HIGHLIGHT tag:"N|🧱|wip-full-solution" %% OEMEC
%% branch "N|🧱: OLTP EFCore multi-entity chassis" %% OEMEC
%% commit type:HIGHLIGHT tag:"N|🧱|wip-oltp-di-efcore-handle-specifications-only-the-rest-is-covered-with-record-types-composition|YourCompany.Configuration.EFCore" %% OEMEC
%% Startup Iteration 7
%% branch "7|💾: EFCore multi EntityEntry visitors" %% EMEEV
%% commit type:NORMAL tag:"7|💾|YourCompany.Configuration.EFCore" %% EMEEV
%% checkout "N|🧱: OLTP EFCore multi-entity chassis" %% EMES
%% branch "7|💾: EFCore multi-entity sorting" %% EMES
%% commit type:NORMAL tag:"7|💾|YourCompany.Configuration.EFCore" %% EMES
%% checkout "7|💾: EFCore multi-entity sorting" %% ESME
%% branch "7|💾: EFCore SortingKey multi-entity" %% ESME
%% merge "7|💾: EFCore multi EntityEntry visitors" type:NORMAL tag:"7|💾|YourCompany.Configuration.EFCore" %% ESME
%% checkout "N|🧱: OLTP EFCore multi-entity chassis" %% ODEI
%% branch "7|🧱: OLTP DI EFCore integrated" %% ODEI
%% commit type:REVERSE %% ODEI>1
%% commit type:REVERSE %% ODEI>2
commit type:HIGHLIGHT tag:"7|🧱|public|oltp-di-efcore-handle-specifications-only-the-rest-is-covered|YourCompany.Configuration.EFCore|YourCompany.OLTP.RecordsManagement.DI.EFCore|YourCompany.OLTP.RecordsManagement.Persistence.Linq.EFCore" %% ODEI
branch "7|🧱: OLTP DI EFCore switch to chassis" %% ODESTC
%% commit type:HIGHLIGHT tag:"7|🧱|oltp-di-efcore-handle-specifications-only-the-rest-is-covered|YourCompany.Configuration.EFCore|YourCompany.OLTP.RecordsManagement.Persistence.Linq.EFCore" %% ODESTC
commit type:NORMAL tag:"7|🧱|YourCompany.Configuration.EFCore|YourCompany.OLTP.RecordsManagement.Persistence.Linq.EFCore" %% ODESTC
%% Startup Iteration 6
checkout "7|🧱: OLTP DI EFCore switch to chassis" %% OEF
branch "6|💾: OLTP EFCore finalized" %% OEF
commit type:NORMAL tag:"6|💾|YourCompany.OLTP.RecordsManagement.Persistence.Linq.EFCore" %% OEF
%% Startup Iteration 5
checkout "6|💾: OLTP EFCore finalized" %% OER
branch "5|💾: OLTP EFCore readonly" %% OER
%% commit type:REVERSE %% OER>1
%% commit type:REVERSE %% OER>2
%% commit type:REVERSE %% OER>3
%% commit type:REVERSE %% OER>4
%% commit type:REVERSE %% OER>5
commit type:NORMAL tag:"5|💾|YourCompany.OLTP.RecordsManagement.Persistence.Linq.EFCore" %% OER
%% checkout "7|🧱: OLTP DI EFCore integrated" %% ODMR
%% checkout "N|🧱: OLTP EFCore multi-entity chassis" %% ODMR
%% branch "5|🧱: OLTP DI mixed repository" %% ODMR
%% commit type:REVERSE %% ODMR>1
%% commit type:REVERSE %% ODMR>2
%% commit type:REVERSE %% ODMR>3
%% commit type:REVERSE %% ODMR>4
%% commit type:REVERSE %% ODMR>5
%% commit type:HIGHLIGHT tag:"5|🧱|oltp-di-combine-use-case-and-persistence-interfaces-with-record-types-composition|YourCompany.OLTP.RecordsManagement.DI.TransactionalComposition" %% ODMR
%% branch "5|🧱: OLTP record composition to chassis" %% ORCTC
%% commit type:HIGHLIGHT tag:"5|🧱|oltp-di-combine-use-case-and-persistence-interfaces-with-record-types-composition|YourCompany.OLTP.RecordsManagement.DI.TransactionalComposition|YourCompany.OLTP.StateOwnership.TransactionalComposition" %% ORCTC
%% commit type:NORMAL tag:"5|🧱|YourCompany.OLTP.RecordsManagement.DI.TransactionalComposition|YourCompany.OLTP.StateOwnership.TransactionalComposition" %% ORCTC
checkout "7|🧱: OLTP DI EFCore switch to chassis" %% ODIFR
branch "5|🧱: OLTP DI inheritance free repo" %% ODIFR
commit type:REVERSE %% ODIFR>1
commit type:HIGHLIGHT tag:"5|🧱|oltp-di-combine-use-case-and-persistence-interfaces-without-inheritance|YourCompany.OLTP.RecordsManagement.DI" %% ODIFR
%% merge "5|🧱: OLTP record composition to chassis" type:HIGHLIGHT tag:"5|🧱|oltp-di-combine-use-case-and-persistence-interfaces-without-inheritance|YourCompany.OLTP.RecordsManagement.DI" %% ODIFR
branch "5|🧱: OLTP DI ScopedUseCasesProvider" %% ODS
commit type:NORMAL tag:"5|🧱|YourCompany.OLTP.RecordsManagement.UseCases.Reflection.DI" %% 5|🧱: OLTP DI ScopedUseCasesProvider
checkout "5|🧱: OLTP DI inheritance free repo" %% ODSRP
branch "5|🧱: OLTP DI ScopedRecordsProvider" %% ODSRP
commit type:NORMAL tag:"5|🧱|YourCompany.OLTP.StateOwnership.Reflection.DI" %% ODSRP
checkout "5|🧱: OLTP DI inheritance free repo" %% OSTC
%% commit type:REVERSE %% OSTC<1
%% commit type:REVERSE %% OSTC<2
%% commit type:REVERSE %% OSTC<3
branch "5|🧱: OLTP switch to chassis" %% OSTC
commit type:REVERSE %% OSTC>1
commit type:HIGHLIGHT tag:"5|🧱|oltp-di-combine-use-case-and-persistence-interfaces-switch-to-chassis|YourCompany.OLTP.RecordsManagement|YourCompany.OLTP.RecordsManagement.DI|YourCompany.OLTP.RecordsManagement.Persistence|YourCompany.OLTP.RecordsManagement.UseCases|YourCompany.OLTP.StateOwnership" %% OSTC
%% Startup Iteration 4
%% checkout "7|💾: EFCore multi-entity sorting" %% CEPFVT
%% branch "4|💾: cache EFProperty from ValueTuple" %% CEPFVT
%% commit type:REVERSE %% CEPFVT>1
%% commit type:REVERSE %% CEPFVT>2
%% commit type:REVERSE %% CEPFVT>3
%% commit type:REVERSE %% CEPFVT>4
%% commit type:REVERSE %% CEPFVT>5
%% commit type:REVERSE %% CEPFVT>6
%% commit type:REVERSE %% CEPFVT>7
%% commit type:REVERSE %% CEPFVT>8
%% commit type:REVERSE %% CEPFVT>9
%% commit type:REVERSE %% CEPFVT>10
%% commit type:REVERSE %% CEPFVT>11
%% commit type:NORMAL tag:"4|💾|YourCompany.Configuration.EFCore" %% CEPFVT
checkout "6|💾: OLTP EFCore finalized" %% EETSKT
branch "4|💾: EFEntityTypeSortingKeyTopology" %% EETSKT
commit type:REVERSE %% EETSKT>1
commit type:REVERSE %% EETSKT>2
commit type:REVERSE %% EETSKT>3
commit type:REVERSE %% EETSKT>4
commit type:REVERSE %% EETSKT>5
%% commit type:REVERSE %% EETSKT>6
%% commit type:REVERSE %% EETSKT>7
commit type:NORMAL tag:"4|💾|YourCompany.Configuration.EFCore" %% EETSKT
checkout "5|💾: OLTP EFCore readonly" %% Startup Iteration 4
commit type:REVERSE %% OER 4>1
commit type:REVERSE %% OER 4>2
commit type:REVERSE %% OER 4>3
checkout "5|💾: OLTP EFCore readonly" %% OEIG
branch "4|💾: OLTP EFCore ID generation" %% OEIG
commit type:REVERSE %% OEIG>1
commit type:NORMAL tag:"4|💾|YourCompany.OLTP.StateOwnership.Reflection.EFCore" %% OEIG
branch "4|💾: OLTP EFCore MetadataHelper" %% OEMH
commit type:NORMAL tag:"4|💾|YourCompany.OLTP.StateOwnership.Reflection.EFCore" %% OEMH
%% checkout "7|💾: EFCore multi EntityEntry visitors" %% Startup Iteration 4
%% commit type:REVERSE %% EMEEV 4>1
%% commit type:REVERSE %% EMEEV 4>2
%% commit type:REVERSE %% EMEEV 4>3
%% commit type:REVERSE %% EMEEV 4>4
%% commit type:REVERSE %% EMEEV 4>5
%% commit type:REVERSE %% EMEEV 4>6
%% commit type:REVERSE %% EMEEV 4>7
%% commit type:REVERSE %% EMEEV 4>8
%% commit type:REVERSE %% EMEEV 4>9
%% commit type:REVERSE %% EMEEV 4>10
%% commit type:REVERSE %% EMEEV 4>11
%% commit type:REVERSE %% EMEEV 4>12
%% commit type:REVERSE %% EMEEV 4>13
checkout "5|💾: OLTP EFCore readonly" %% ESKEE
branch "4|💾: EFCore SortingKey ⇆ EntityEntry" %% ESKEE
commit type:REVERSE %% ESKEE>1
commit type:REVERSE %% ESKEE>2
commit type:REVERSE %% ESKEE>3
commit type:NORMAL tag:"4|💾|YourCompany.Configuration.EFCore" %% ESKEE
%% merge "7|💾: EFCore multi EntityEntry visitors" type:NORMAL tag:"4|💾|YourCompany.Configuration.EFCore" %% ESKEE
branch "4|💾: EFEntityEntryPropertiesCache" %% EEEPC
commit type:NORMAL tag:"4|💾|YourCompany.Configuration.EFCore" %% EEEPC
%% checkout "7|💾: EFCore multi-entity sorting" %% Startup Iteration 4
%% commit type:REVERSE %% EMES 4>1
%% commit type:REVERSE %% EMES 4>2
%% commit type:REVERSE %% EMES 4>3
%% commit type:REVERSE %% EMES 4>4
%% commit type:REVERSE %% EMES 4>5
%% commit type:REVERSE %% EMES 4>6
%% commit type:REVERSE %% EMES 4>7
%% commit type:REVERSE %% EMES 4>8
%% commit type:REVERSE %% EMES 4>9
%% commit type:REVERSE %% EMES 4>10
%% commit type:REVERSE %% EMES 4>11
%% commit type:REVERSE %% EMES 4>12
%% commit type:REVERSE %% EMES 4>13
%% commit type:REVERSE %% EMES 4>14
%% commit type:REVERSE %% EMES 4>15
%% commit type:REVERSE %% EMES 4>16
checkout "5|💾: OLTP EFCore readonly" %% ESKR
branch "4|💾: EFCore SortingKey reading" %% ESKR
commit type:REVERSE %% ESKR>1
commit type:REVERSE %% ESKR>2
commit type:REVERSE %% ESKR>3
commit type:REVERSE %% ESKR>4
commit type:REVERSE %% ESKR>5
commit type:NORMAL tag:"4|💾|YourCompany.Configuration.EFCore" %% ESKR
%% merge "7|💾: EFCore multi-entity sorting" type:NORMAL tag:"4|💾|YourCompany.Configuration.EFCore" %% ESKR
checkout "5|🧱: OLTP switch to chassis" %% OLMBU
branch "4|🧱: OLTP LINQ may be useful" %% OLMBU
%% commit type:HIGHLIGHT tag:"4|🧱|oltp-segregate-persistence-repository-is-for-use-cases|YourCompany.OLTP.RecordsManagement.Persistence.Linq" %% OLMBU
merge "5|💾: OLTP EFCore readonly" type:HIGHLIGHT tag:"4|🧱|oltp-segregate-persistence-repository-is-for-use-cases|YourCompany.OLTP.RecordsManagement.Persistence.Linq" %% OLMBU
branch "4|🧱: OLTP identities are unique keys" %% OIAUK
%% commit type:REVERSE %% OIAUK>1
%% commit type:HIGHLIGHT tag:"4|🧱|oltp-segregate-persistence-repository-is-for-use-cases|YourCompany.OLTP.RecordsManagement.Persistence" %% OIAUK
commit type:NORMAL tag:"4|🧱|YourCompany.OLTP.RecordsManagement.Persistence" %% OIAUK
%% checkout "5|🧱: OLTP record composition to chassis" %% OUCBRT
%% branch "4|🏠: OLTP use cases by record type" %% OUCBRT
%% commit type:REVERSE %% OUCBRT>1
%% commit type:REVERSE %% OUCBRT>2
%% commit type:REVERSE %% OUCBRT>3
%% commit type:REVERSE %% OUCBRT>4
%% commit type:REVERSE %% OUCBRT>5
%% commit type:HIGHLIGHT tag:"4|🏠|oltp-segregate-use-cases-with-transactional-composition|YourCompany.OLTP.RecordsManagement.UseCases.TransactionalComposition" %% OUCBRT
%% checkout "4|🏠: OLTP use cases by record type" %% EOUC
checkout "5|🧱: OLTP switch to chassis" %% EOUC
branch "4|🏠: enumerate OLTP use cases" %% EOUC
commit type:HIGHLIGHT tag:"4|🏠|oltp-segregate-use-cases-repository-is-for-persistence|YourCompany.OLTP.RecordsManagement.UseCases" %% EOUC
%% merge "4|🏠: OLTP use cases by record type" type:HIGHLIGHT tag:"4|🏠|oltp-segregate-use-cases-repository-is-for-persistence|YourCompany.OLTP.RecordsManagement.UseCases" %% EOUC
%% Startup Iteration 3
checkout "4|💾: EFEntityTypeSortingKeyTopology" %% Startup Iteration 3
commit type:REVERSE %% EETSKT 3>1
commit type:REVERSE %% EETSKT 3>2
commit type:REVERSE %% EETSKT 3>3
commit type:REVERSE %% EETSKT 3>4
commit type:REVERSE %% EETSKT 3>5
%% commit type:REVERSE %% EETSKT 3>6
%% checkout "4|💾: EFCore SortingKey ⇆ EntityEntry" %% Startup Iteration 3
%% commit type:REVERSE %% ESKEE 3>1
checkout "4|💾: EFCore SortingKey ⇆ EntityEntry" %% EFCSK
%% checkout "7|💾: EFCore SortingKey multi-entity" %% EFCSK
branch "3|💾: EFCore first-class SortingKey" %% EFCSK
%% merge "4|💾: EFCore SortingKey ⇆ EntityEntry" %% EFCSK
merge "4|💾: EFCore SortingKey reading" %% EFCSK
%% merge "4|💾: EFCore SortingKey ⇆ EntityEntry" %% EFCSK
merge "4|💾: EFEntityTypeSortingKeyTopology" %% EFCSK
commit type:REVERSE %% EFCSK>1
%% commit type:REVERSE %% EFCSK>2
%% commit type:REVERSE %% EFCSK>3
%% commit type:REVERSE %% EFCSK>4
commit type:NORMAL tag:"3|💾|YourCompany.Configuration.EFCore|YourCompany.Configuration.EFCore.PostgreSQL|YourCompany.Configuration.EFCore.Sqlite" %% EFCSK
%% checkout "4|💾: cache EFProperty from ValueTuple" %% Startup Iteration 3
%% commit type:REVERSE %% CEPFVT 3>1
%% commit type:REVERSE %% CEPFVT 3>2
%% commit type:REVERSE %% CEPFVT 3>3
%% commit type:REVERSE %% CEPFVT 3>4
%% commit type:REVERSE %% CEPFVT 3>5
%% commit type:REVERSE %% CEPFVT 3>6
%% commit type:REVERSE %% CEPFVT 3>7
%% checkout "3|💾: EFCore first-class SortingKey" %% EPEC
branch "3|💾: EFPropertyExpressionsCache" %% EPEC
commit type:NORMAL tag:"3|💾|YourCompany.Configuration.EFCore" %% EPEC
%% merge "4|💾: cache EFProperty from ValueTuple" type:NORMAL tag:"3|💾|YourCompany.Configuration.EFCore" %% EPEC
%% checkout "4|🧱: OLTP identities are unique keys" %% Startup Iteration 3
%% commit type:REVERSE %% OIAUK 3>1
checkout "4|🏠: enumerate OLTP use cases" %% OTS
%% checkout "4|🧱: OLTP identities are unique keys" %% OTS
branch "3|🧱: OLTP transaction structure" %% OTS
merge "4|🧱: OLTP identities are unique keys" %% OTS
commit type:REVERSE %% OTS>1
commit type:REVERSE %% OTS>2
commit type:REVERSE %% OTS>3
commit type:REVERSE %% OTS>4
commit type:REVERSE %% OTS>5
commit type:REVERSE %% OTS>6
%% commit type:REVERSE %% OTS>7
commit type:HIGHLIGHT tag:"3|🧱|oltp-typical-transaction-structure-repository-is-up-to-you|YourCompany.OLTP.RecordsManagement" %% OTS
%% merge "4|🧱: OLTP identities are unique keys" type:HIGHLIGHT tag:"3|🧱|oltp-typical-transaction-structure-repository-is-up-to-you|YourCompany.OLTP.RecordsManagement" %% OTS
%% checkout "4|🏠: OLTP use cases by record type" %% ORTCM
%% branch "3|🏠: OLTP RecordTypesCompositionMap" %% ORTCM
%% commit type:REVERSE %% ORTCM>1
%% commit type:REVERSE %% ORTCM>2
%% commit type:REVERSE %% ORTCM>3
%% commit type:REVERSE %% ORTCM>4
%% commit type:REVERSE %% ORTCM>5
%% commit type:REVERSE %% ORTCM>6
%% commit type:REVERSE %% ORTCM>7
%% commit type:REVERSE %% ORTCM>8
%% commit type:REVERSE %% ORTCM>9
%% commit type:REVERSE %% ORTCM>10
%% commit type:NORMAL tag:"3|🏠|YourCompany.OLTP.StateOwnership.TransactionalComposition.Reflection" %% ORTCM
checkout "5|🧱: OLTP DI ScopedUseCasesProvider" %% OUCTM
commit type:REVERSE %% OUCTM<1
commit type:REVERSE %% OUCTM<2
commit type:REVERSE %% OUCTM<3
commit type:REVERSE %% OUCTM<4
commit type:REVERSE %% OUCTM<5
commit type:REVERSE %% OUCTM<6
commit type:REVERSE %% OUCTM<7
commit type:REVERSE %% OUCTM<8
commit type:REVERSE %% OUCTM<9
commit type:REVERSE %% OUCTM<10
commit type:REVERSE %% OUCTM<11
%% commit type:REVERSE %% OUCTM<12
%% commit type:REVERSE %% OUCTM<13
%% commit type:REVERSE %% OUCTM<14
%% commit type:REVERSE %% OUCTM<15
branch "3|🏠: OLTP UseCaseTypesMap" %% OUCTM
%% commit type:REVERSE %% OUCTM>1
%% commit type:REVERSE %% OUCTM>2
%% commit type:REVERSE %% OUCTM>3
%% commit type:REVERSE %% OUCTM>4
%% commit type:REVERSE %% OUCTM>5
%% commit type:REVERSE %% OUCTM>6
%% commit type:REVERSE %% OUCTM>7
commit type:NORMAL tag:"3|🏠|YourCompany.OLTP.RecordsManagement.UseCases.Reflection" %% OUCTM
checkout "4|🏠: enumerate OLTP use cases" %% GOUC
branch "3|🏠: generic OLTP use cases" %% GOUC
%% commit type:REVERSE %% GOUC>1
%% commit type:NORMAL tag:"3|🏠|YourCompany.OLTP.RecordsManagement.UseCases" %% GOUC
merge "3|🏠: OLTP UseCaseTypesMap" type:NORMAL tag:"3|🏠|YourCompany.OLTP.RecordsManagement.UseCases" %% GOUC
checkout "4|💾: OLTP EFCore MetadataHelper" %% Startup Iteration 3
commit type:REVERSE %% OEMH 3>1
commit type:REVERSE %% OEMH 3>2
commit type:REVERSE %% OEMH 3>3
commit type:REVERSE %% OEMH 3>4
commit type:REVERSE %% OEMH 3>5
commit type:REVERSE %% OEMH 3>6
commit type:REVERSE %% OEMH 3>7
commit type:REVERSE %% OEMH 3>8
commit type:REVERSE %% OEMH 3>9
commit type:REVERSE %% OEMH 3>10
%% commit type:REVERSE %% OEMH 3>11
%% commit type:REVERSE %% OEMH 3>12
%% commit type:REVERSE %% OEMH 3>13
%% commit type:REVERSE %% OEMH 3>14
%% checkout "3|🏠: OLTP RecordTypesCompositionMap" %% ORTM
checkout "5|🧱: OLTP DI ScopedRecordsProvider" %% ORTM
branch "3|🏠: OLTP RecordTypesMap" %% ORTM
%% merge "3|🏠: OLTP RecordTypesCompositionMap" %% ORTM
%% commit type:REVERSE %% ORTM>1
%% commit type:REVERSE %% ORTM>2
%% commit type:REVERSE %% ORTM>3
%% commit type:REVERSE %% ORTM>4
%% commit type:REVERSE %% ORTM>5
%% commit type:NORMAL tag:"3|🏠|YourCompany.OLTP.StateOwnership.Reflection" %% ORTM
%% merge "3|🏠: OLTP RecordTypesCompositionMap" type:NORMAL tag:"3|🏠|YourCompany.OLTP.StateOwnership.Reflection" %% ORTM
merge "4|💾: OLTP EFCore MetadataHelper" type:NORMAL tag:"3|🏠|YourCompany.OLTP.StateOwnership.Reflection" %% ORTM
%% Startup Iteration 2
%% checkout "N|🧱: wip switch to chassis" %% EHMR
%% branch "2|💾: EFCore hosting migration run" %% EHMR
%% commit type:REVERSE %% EHMR>1
%% commit type:REVERSE %% EHMR>2
%% commit type:REVERSE %% EHMR>3
%% commit type:REVERSE %% EHMR>4
%% commit type:REVERSE %% EHMR>5
%% commit type:REVERSE %% EHMR>6
%% commit type:REVERSE %% EHMR>7
%% commit type:REVERSE %% EHMR>8
%% commit type:REVERSE %% EHMR>9
%% commit type:REVERSE %% EHMR>10
%% commit type:REVERSE %% EHMR>11
%% commit type:REVERSE %% EHMR>12
%% commit type:REVERSE %% EHMR>13
%% commit type:REVERSE %% EHMR>14
%% commit type:REVERSE %% EHMR>15
%% commit type:REVERSE %% EHMR>16
%% commit type:REVERSE %% EHMR>17
%% commit type:REVERSE %% EHMR>18
%% commit type:REVERSE %% EHMR>19
%% commit type:REVERSE %% EHMR>20
%% commit type:REVERSE %% EHMR>21
%% commit type:REVERSE %% EHMR>22
%% commit type:REVERSE %% EHMR>23
%% commit type:REVERSE %% EHMR>24
%% commit type:REVERSE %% EHMR>25
%% commit type:REVERSE %% EHMR>26
%% commit type:REVERSE %% EHMR>27
%% commit type:REVERSE %% EHMR>28
%% commit type:REVERSE %% EHMR>29
%% commit type:REVERSE %% EHMR>30
%% commit type:REVERSE %% EHMR>31
%% commit type:REVERSE %% EHMR>32
%% commit type:REVERSE %% EHMR>33
%% commit type:NORMAL tag:"2|💾|YourCompany.Configuration.EFCore.Hosting" %% EHMR
checkout "6|💾: OLTP EFCore finalized" %% ECTTGS
commit type:REVERSE %% ECTTGS<1
commit type:REVERSE %% ECTTGS<2
commit type:REVERSE %% ECTTGS<3
commit type:REVERSE %% ECTTGS<4
commit type:REVERSE %% ECTTGS<5
commit type:REVERSE %% ECTTGS<6
commit type:REVERSE %% ECTTGS<7
commit type:REVERSE %% ECTTGS<8
commit type:REVERSE %% ECTTGS<9
commit type:REVERSE %% ECTTGS<10
commit type:REVERSE %% ECTTGS<11
commit type:REVERSE %% ECTTGS<12
commit type:REVERSE %% ECTTGS<13
commit type:REVERSE %% ECTTGS<14
commit type:REVERSE %% ECTTGS<15
commit type:REVERSE %% ECTTGS<16
commit type:REVERSE %% ECTTGS<17
commit type:REVERSE %% ECTTGS<18
commit type:REVERSE %% ECTTGS<19
%% commit type:REVERSE %% ECTTGS<20
%% commit type:REVERSE %% ECTTGS<21
%% commit type:REVERSE %% ECTTGS<22
%% commit type:REVERSE %% ECTTGS<23
%% commit type:REVERSE %% ECTTGS<24
%% commit type:REVERSE %% ECTTGS<25
branch "2|💾: EFChangeTrackerTrackGraphStrategy" %% ECTTGS
commit type:NORMAL tag:"2|💾|YourCompany.Configuration.EFCore" %% ECTTGS
checkout "6|💾: OLTP EFCore finalized" %% EPL
branch "2|💾: EFCore pessimistic locking" %% EPL
commit type:NORMAL tag:"2|💾|YourCompany.Configuration.EFCore|YourCompany.Configuration.EFCore.PostgreSQL|YourCompany.Configuration.EFCore.Sqlite" %% EPL
checkout "4|💾: EFEntityEntryPropertiesCache" %% BPE
branch "2|💾: basic pluggable EFCore" %% BPE
checkout "2|💾: EFChangeTrackerTrackGraphStrategy" %% BPE
commit type:REVERSE %% ECTTGS BPE>1
checkout "2|💾: basic pluggable EFCore" %% BPE
merge "3|💾: EFPropertyExpressionsCache" %% BPE
merge "2|💾: EFCore pessimistic locking" %% BPE
%% merge "2|💾: EFChangeTrackerTrackGraphStrategy" %% BPE
merge "2|💾: EFChangeTrackerTrackGraphStrategy" type:NORMAL tag:"2|💾|YourCompany.Configuration.EFCore|YourCompany.Configuration.EFCore.PostgreSQL|YourCompany.Configuration.EFCore.Sqlite" %% BPE
%% merge "2|💾: EFCore hosting migration run" type:NORMAL tag:"2|💾|YourCompany.Configuration.EFCore|YourCompany.Configuration.EFCore.PostgreSQL|YourCompany.Configuration.EFCore.Sqlite" %% BPE
%% checkout "3|🏠: OLTP RecordTypesCompositionMap" %% TCM
%% branch "2|🧱: TypesCompositionMap" %% TCM
%% commit type:REVERSE %% TCM>1
%% commit type:REVERSE %% TCM>2
%% commit type:REVERSE %% TCM>3
%% commit type:REVERSE %% TCM>4
%% commit type:REVERSE %% TCM>5
%% commit type:REVERSE %% TCM>6
%% commit type:REVERSE %% TCM>7
%% commit type:REVERSE %% TCM>8
%% commit type:NORMAL tag:"2|🧱|YourCompany.Reflection" %% TCM
checkout "3|🏠: OLTP UseCaseTypesMap" %% TAH
%% commit type:REVERSE %% TAH<1
%% commit type:REVERSE %% TAH<2
branch "2|🧱: TypeAbstractionsHelper" %% TAH
commit type:REVERSE %% TAH>1
commit type:REVERSE %% TAH>2
commit type:REVERSE %% TAH>3
commit type:REVERSE %% TAH>4
commit type:REVERSE %% TAH>5
commit type:NORMAL tag:"2|🧱|YourCompany.Reflection" %% TAH
%% merge "2|🧱: TypesCompositionMap" type:NORMAL tag:"2|🧱|YourCompany.Reflection" %% TAH
checkout "4|💾: EFCore SortingKey reading" %% VTH
%% commit type:REVERSE %% VTH<1
%% commit type:REVERSE %% VTH<2
%% commit type:REVERSE %% VTH<3
%% commit type:REVERSE %% VTH<4
branch "2|🧱: ValueTupleHelper" %% VTH
%% merge "4|💾: cache EFProperty from ValueTuple" %% VTH
commit type:REVERSE %% VTH>1
commit type:REVERSE %% VTH>2
commit type:REVERSE %% VTH>3
commit type:REVERSE %% VTH>4
commit type:REVERSE %% VTH>5
commit type:REVERSE %% VTH>6
commit type:REVERSE %% VTH>7
commit type:REVERSE %% VTH>8
commit type:REVERSE %% VTH>9
commit type:NORMAL tag:"2|🧱|YourCompany.Reflection" %% VTH
checkout "5|🧱: OLTP DI ScopedRecordsProvider" %% DCH
branch "2|🧱: DIConstructorHelper" %% DCH
commit type:REVERSE %% DCH>1
commit type:REVERSE %% DCH>2
commit type:REVERSE %% DCH>3
commit type:REVERSE %% DCH>4
commit type:REVERSE %% DCH>5
commit type:REVERSE %% DCH>6
commit type:REVERSE %% DCH>7
commit type:REVERSE %% DCH>8
commit type:REVERSE %% DCH>9
commit type:REVERSE %% DCH>10
commit type:REVERSE %% DCH>11
commit type:REVERSE %% DCH>12
commit type:REVERSE %% DCH>13
commit type:REVERSE %% DCH>14
commit type:REVERSE %% DCH>15
commit type:REVERSE %% DCH>16
commit type:REVERSE %% DCH>17
%% commit type:REVERSE %% DCH>18
%% commit type:REVERSE %% DCH>19
%% commit type:REVERSE %% DCH>20
%% commit type:REVERSE %% DCH>21
%% commit type:REVERSE %% DCH>22
commit type:NORMAL tag:"2|🧱|YourCompany.Reflection.DI" %% DCH
checkout "3|💾: EFPropertyExpressionsCache" %% Startup Iteration 2
commit type:REVERSE %% EPEC 2>1
%% checkout "2|🧱: TypeAbstractionsHelper" %% GMH
checkout "4|💾: EFEntityEntryPropertiesCache" %% GMH
branch "2|🧱: GetMemberHelper" %% GMH
merge "3|💾: EFPropertyExpressionsCache" %% GMH
%% commit type:NORMAL tag:"2|🧱|YourCompany.Reflection" %% GMH
merge "2|🧱: DIConstructorHelper" type:NORMAL tag:"2|🧱|YourCompany.Reflection" %% GMH
checkout "3|🏠: generic OLTP use cases" %% ATL
branch "2|🧱: AwaitTasksList" %% ATL
commit type:REVERSE %% ATL>1
commit type:REVERSE %% ATL>2
commit type:REVERSE %% ATL>3
commit type:REVERSE %% ATL>4
commit type:REVERSE %% ATL>5
commit type:NORMAL tag:"2|🧱|YourCompany.Threading" %% ATL
checkout "4|🧱: OLTP identities are unique keys" %% SH
branch "2|🧱: StructHelper" %% SH
commit type:REVERSE %% SH>1
commit type:REVERSE %% SH>2
commit type:REVERSE %% SH>3
commit type:REVERSE %% SH>4
commit type:REVERSE %% SH>5
commit type:REVERSE %% SH>6
commit type:REVERSE %% SH>7
commit type:REVERSE %% SH>8
commit type:REVERSE %% SH>9
commit type:REVERSE %% SH>10
commit type:REVERSE %% SH>11
commit type:REVERSE %% SH>12
commit type:REVERSE %% SH>13
commit type:REVERSE %% SH>14
%% commit type:REVERSE %% SH>15
%% commit type:REVERSE %% SH>16
%% commit type:REVERSE %% SH>17
%% commit type:REVERSE %% SH>18
commit type:NORMAL tag:"2|🧱|YourCompany.CompilerServices" %% SH
checkout "3|🧱: OLTP transaction structure" %% Startup Iteration 2
commit type:REVERSE %% OTS 2>1
commit type:REVERSE %% OTS 2>2
commit type:REVERSE %% OTS 2>3
commit type:REVERSE %% OTS 2>4
commit type:REVERSE %% OTS 2>5
commit type:REVERSE %% OTS 2>6
commit type:REVERSE %% OTS 2>7
commit type:REVERSE %% OTS 2>8
%% commit type:REVERSE %% OTS 2>9
%% commit type:REVERSE %% OTS 2>10
%% commit type:REVERSE %% OTS 2>11
%% commit type:REVERSE %% OTS 2>12
checkout "3|🏠: generic OLTP use cases" %% OTILS
%% checkout "3|🧱: OLTP transaction structure" %% OTILS
branch "2|🏠: OLTP transaction is limited size" %% OTILS
%% commit type:HIGHLIGHT tag:"2|🏠|oltp-ways-to-access-size-limited-record-batch|YourCompany.OLTP.RecordsManagement" %% OTILS
merge "3|🧱: OLTP transaction structure" type:HIGHLIGHT tag:"2|🏠|oltp-ways-to-access-size-limited-record-batch|YourCompany.OLTP.RecordsManagement" %% OTILS
%% Startup Iteration 1
%% checkout "MERGED" %% BCC
checkout "2|💾: basic pluggable EFCore" %% BCC
branch "1|🧱: basic configurations covered" %% BCC
commit type:REVERSE %% BCC>1
%% commit type:REVERSE %% BCC>2
%% commit type:REVERSE %% BCC>3
%% commit type:REVERSE %% BCC>4
commit type:HIGHLIGHT tag:"1|🧱|configuration-entry-assembly-rotating-secrets-scaling-plugins|YourCompany.Configuration" %% BCC
%% checkout "3|🏠: OLTP RecordTypesCompositionMap" %% OTC
%% commit type:REVERSE %% OTC<1
%% commit type:REVERSE %% OTC<2
%% commit type:REVERSE %% OTC<3
%% commit type:REVERSE %% OTC<4
%% commit type:REVERSE %% OTC<5
%% commit type:REVERSE %% OTC<6
%% commit type:REVERSE %% OTC<7
%% commit type:REVERSE %% OTC<8
%% commit type:REVERSE %% OTC<9
%% commit type:REVERSE %% OTC<10
%% commit type:REVERSE %% OTC<11
%% commit type:REVERSE %% OTC<12
%% commit type:REVERSE %% OTC<13
%% commit type:REVERSE %% OTC<14
%% commit type:REVERSE %% OTC<15
%% commit type:REVERSE %% OTC<16
%% commit type:REVERSE %% OTC<17
%% commit type:REVERSE %% OTC<18
%% commit type:REVERSE %% OTC<19
%% commit type:REVERSE %% OTC<20
%% branch "1|🏠: OLTP transactional composition" %% OTC
%% commit type:REVERSE %% OTC>1
%% commit type:REVERSE %% OTC>2
%% commit type:REVERSE %% OTC>3
%% commit type:REVERSE %% OTC>4
%% commit type:REVERSE %% OTC>5
%% commit type:REVERSE %% OTC>6
%% commit type:REVERSE %% OTC>7
%% commit type:REVERSE %% OTC>8
%% commit type:REVERSE %% OTC>9
%% commit type:REVERSE %% OTC>10
%% commit type:REVERSE %% OTC>11
%% commit type:REVERSE %% OTC>12
%% commit type:REVERSE %% OTC>13
%% commit type:REVERSE %% OTC>14
%% commit type:NORMAL tag:"1|🏠|YourCompany.OLTP.StateOwnership.TransactionalComposition" %% OTC
%% checkout "N|🧱: wip switch to chassis" %% OEP
%% commit type:REVERSE %% OEP<1
%% commit type:REVERSE %% OEP<2
%% commit type:REVERSE %% OEP<3
%% commit type:REVERSE %% OEP<4
%% commit type:REVERSE %% OEP<5
%% commit type:REVERSE %% OEP<6
%% commit type:REVERSE %% OEP<7
%% commit type:REVERSE %% OEP<8
%% commit type:REVERSE %% OEP<9
%% commit type:REVERSE %% OEP<10
%% commit type:REVERSE %% OEP<11
%% commit type:REVERSE %% OEP<12
%% commit type:REVERSE %% OEP<13
%% commit type:REVERSE %% OEP<14
%% commit type:REVERSE %% OEP<15
%% commit type:REVERSE %% OEP<16
%% commit type:REVERSE %% OEP<17
%% commit type:REVERSE %% OEP<18
%% commit type:REVERSE %% OEP<19
%% branch "1|🏠: OLTP events producing" %% OEP
%% commit type:REVERSE %% OEP>1
%% commit type:REVERSE %% OEP>2
%% commit type:REVERSE %% OEP>3
%% commit type:REVERSE %% OEP>4
%% commit type:REVERSE %% OEP>5
%% commit type:REVERSE %% OEP>6
%% commit type:REVERSE %% OEP>7
%% commit type:REVERSE %% OEP>8
%% commit type:REVERSE %% OEP>9
%% commit type:REVERSE %% OEP>10
%% commit type:REVERSE %% OEP>11
%% commit type:REVERSE %% OEP>12
%% commit type:REVERSE %% OEP>13
%% commit type:REVERSE %% OEP>14
%% commit type:REVERSE %% OEP>15
%% commit type:REVERSE %% OEP>16
%% commit type:REVERSE %% OEP>17
%% commit type:REVERSE %% OEP>18
%% commit type:REVERSE %% OEP>19
%% commit type:REVERSE %% OEP>20
%% commit type:REVERSE %% OEP>21
%% commit type:REVERSE %% OEP>22
%% commit type:REVERSE %% OEP>23
%% commit type:REVERSE %% OEP>24
%% commit type:REVERSE %% OEP>25
%% commit type:REVERSE %% OEP>26
%% commit type:REVERSE %% OEP>27
%% commit type:REVERSE %% OEP>28
%% commit type:REVERSE %% OEP>29
%% commit type:REVERSE %% OEP>30
%% commit type:REVERSE %% OEP>31
%% commit type:REVERSE %% OEP>32
%% commit type:REVERSE %% OEP>33
%% commit type:REVERSE %% OEP>34
%% commit type:REVERSE %% OEP>35
%% commit type:REVERSE %% OEP>36
%% commit type:NORMAL tag:"1|🏠|YourCompany.OLTP.StateOwnership.EventsProducing" %% OEP
checkout "2|🏠: OLTP transaction is limited size" %% Startup Iteration 1
commit type:REVERSE %% OTILS 1>1
%% commit type:REVERSE %% OTILS 1>2
%% commit type:REVERSE %% OTILS 1>3
%% checkout MERGED %% THOOIT
checkout "2|🏠: OLTP transaction is limited size" %% THOOIT
checkout "3|🏠: OLTP RecordTypesMap" %% THOOIT
branch "1|🏠: the heart of OLTP is transaction" %% THOOIT
%% merge "2|🏠: OLTP transaction is limited size" %% THOOIT
%% merge "1|🏠: OLTP events producing" %% THOOIT
%% merge "1|🏠: OLTP transactional composition" %% THOOIT
%% merge "N|🧱: wip switch to chassis" %% THOOIT
%% commit type:HIGHLIGHT tag:"1|🏠|oltp-basic-object-model-the-rest-is-up-to-you|YourCompany.OLTP.StateOwnership" %% THOOIT
merge "2|🏠: OLTP transaction is limited size" type:HIGHLIGHT tag:"1|🏠|oltp-basic-object-model-the-rest-is-up-to-you|YourCompany.OLTP.StateOwnership" %% THOOIT
Still reading? 🥳 Hopefully the above and what expects you next
resonates to your professional experience 🤞
With any comments, thanks or other feedback please contact me at
gzorik.us@gmail.com.
Looking forward to a productive conversation with you 👀
Now let's dive in into the entry point branches available. It's sorted
by complexity decrease top to bottom. The first block is the current
solution, the latest is a template.
Note when you checkout the particular entry point it won't contain
any fixups yet made after publishing. You'll only see the latter in a
next entry points graph version. See also the detailed notes in
Branching rules and Versioning.
Files: 203 | Lines: 17310
Pros: out-of-the-box full-fledged persistence utilizing the linq record data builders
Cons: significant entry point complexity increase because of covering EFCore missing capabilities
| Log | Examples | Modules |
|---|---|---|
| 1|🏠: the heart of OLTP is transaction | TODO | YourCompany.OLTP.StateOwnership (+371 lines) |
| 1|🧱: basic configurations covered | TODO | YourCompany.Configuration (+637 lines) |
| 2|🏠: OLTP transaction is limited size | TODO | YourCompany.OLTP.RecordsManagement (+1500 lines) |
| 2|🧱: StructHelper | TODO | YourCompany.CompilerServices (+18 lines) |
| 2|🧱: AwaitTasksList | TODO | YourCompany.Threading (+49 lines) |
| 2|🧱: GetMemberHelper | TODO | YourCompany.Reflection (+57 lines) |
| 2|🧱: DIConstructorHelper | TODO | YourCompany.Reflection.DI (+31 lines) |
| 2|🧱: ValueTupleHelper | TODO | YourCompany.Reflection (+143 lines) |
| 2|🧱: TypeAbstractionsHelper | TODO | YourCompany.Reflection (+26 lines) |
| 2|💾: basic pluggable EFCore | efcore‑migrations | YourCompany.Configuration.EFCore (+429 lines) YourCompany.Configuration.EFCore.PostgreSQL (+181 lines) YourCompany.Configuration.EFCore.Sqlite (+71 lines) |
| 2|💾: EFCore pessimistic locking | TODO | YourCompany.Configuration.EFCore (+222 lines) YourCompany.Configuration.EFCore.PostgreSQL (+59 lines) YourCompany.Configuration.EFCore.Sqlite (+47 lines) |
| 2|💾: EFChangeTrackerTrackGraphStrategy | TODO | YourCompany.Configuration.EFCore (+106 lines) |
| 3|🏠: OLTP RecordTypesMap | TODO | YourCompany.OLTP.StateOwnership.Reflection (+263 lines) |
| 3|🏠: generic OLTP use cases | TODO | YourCompany.OLTP.RecordsManagement.UseCases (+212 lines) |
| 3|🏠: OLTP UseCaseTypesMap | TODO | YourCompany.OLTP.RecordsManagement.UseCases.Reflection (+176 lines) |
| 3|🧱: OLTP transaction structure | TODO | YourCompany.OLTP.RecordsManagement (+1918 lines) |
| 3|💾: EFPropertyExpressionsCache | TODO | YourCompany.Configuration.EFCore (+87 lines) |
| 3|💾: EFCore first-class SortingKey | TODO | YourCompany.Configuration.EFCore (+2388 lines) YourCompany.Configuration.EFCore.PostgreSQL (+37 lines) YourCompany.Configuration.EFCore.Sqlite (+37 lines) |
| 4|🏠: enumerate OLTP use cases | TODO | YourCompany.OLTP.RecordsManagement.UseCases (+117 lines) |
| 4|🧱: OLTP identities are unique keys | TODO | YourCompany.OLTP.RecordsManagement.Persistence (+1642 lines) |
| 4|🧱: OLTP LINQ may be useful | TODO | YourCompany.OLTP.RecordsManagement.Persistence.Linq (+59 lines) |
| 4|💾: EFCore SortingKey reading | TODO | YourCompany.Configuration.EFCore (+789 lines) |
| 4|💾: EFEntityEntryPropertiesCache | TODO | YourCompany.Configuration.EFCore (+63 lines) |
| 4|💾: EFCore SortingKey ⇆ EntityEntry | TODO | YourCompany.Configuration.EFCore (+763 lines) |
| 4|💾: OLTP EFCore MetadataHelper | TODO | YourCompany.OLTP.StateOwnership.Reflection.EFCore (+45 lines) |
| 4|💾: OLTP EFCore ID generation | TODO | YourCompany.OLTP.StateOwnership.Reflection.EFCore (+111 lines) |
| 4|💾: EFEntityTypeSortingKeyTopology | TODO | YourCompany.Configuration.EFCore (+347 lines) |
| 5|🧱: OLTP switch to chassis | TODO | YourCompany.OLTP.RecordsManagement (+1 lines) YourCompany.OLTP.RecordsManagement.DI (+122 lines) YourCompany.OLTP.RecordsManagement.Persistence (-26 lines) YourCompany.OLTP.RecordsManagement.UseCases (-117 lines) YourCompany.OLTP.StateOwnership (+6 lines) |
| 5|🧱: OLTP DI ScopedRecordsProvider | TODO | YourCompany.OLTP.StateOwnership.Reflection.DI (+120 lines) |
| 5|🧱: OLTP DI ScopedUseCasesProvider | TODO | YourCompany.OLTP.RecordsManagement.UseCases.Reflection.DI (+69 lines) |
| 5|🧱: OLTP DI inheritance free repo | TODO | YourCompany.OLTP.RecordsManagement.DI (+444 lines) |
| 5|💾: OLTP EFCore readonly | TODO | YourCompany.OLTP.RecordsManagement.Persistence.Linq.EFCore (+2256 lines) |
| 6|💾: OLTP EFCore finalized | TODO | YourCompany.OLTP.RecordsManagement.Persistence.Linq.EFCore (+1108 lines) |
| 7|🧱: OLTP DI EFCore switch to chassis | TODO | YourCompany.Configuration.EFCore (+4 lines) YourCompany.OLTP.RecordsManagement.Persistence.Linq.EFCore (+1 lines) |
| 7|🧱: OLTP DI EFCore integrated | efcore‑migrations | YourCompany.Configuration.EFCore (0 lines) YourCompany.OLTP.RecordsManagement.DI.EFCore (+319 lines) YourCompany.OLTP.RecordsManagement.Persistence.Linq.EFCore (+2 lines) |
Files: 82 | Lines: 7058
Pros: avoid inheriting per entity, contravariant use cases auto-injection, good starting point for adapters
Cons: still lacking major things like events producing, transactional composition (domain modularity), persistence
| Log | Examples | Modules |
|---|---|---|
| 1|🏠: the heart of OLTP is transaction | TODO | YourCompany.OLTP.StateOwnership (+371 lines) |
| 2|🏠: OLTP transaction is limited size | TODO | YourCompany.OLTP.RecordsManagement (+1500 lines) |
| 2|🧱: StructHelper | TODO | YourCompany.CompilerServices (+18 lines) |
| 2|🧱: AwaitTasksList | TODO | YourCompany.Threading (+49 lines) |
| 2|🧱: GetMemberHelper | TODO | YourCompany.Reflection (+57 lines) |
| 2|🧱: DIConstructorHelper | TODO | YourCompany.Reflection.DI (+31 lines) |
| 2|🧱: TypeAbstractionsHelper | TODO | YourCompany.Reflection (+26 lines) |
| 3|🏠: OLTP RecordTypesMap | TODO | YourCompany.OLTP.StateOwnership.Reflection (+263 lines) |
| 3|🏠: generic OLTP use cases | TODO | YourCompany.OLTP.RecordsManagement.UseCases (+212 lines) |
| 3|🏠: OLTP UseCaseTypesMap | TODO | YourCompany.OLTP.RecordsManagement.UseCases.Reflection (+176 lines) |
| 3|🧱: OLTP transaction structure | TODO | YourCompany.OLTP.RecordsManagement (+1918 lines) |
| 4|🏠: enumerate OLTP use cases | TODO | YourCompany.OLTP.RecordsManagement.UseCases (+117 lines) |
| 4|🧱: OLTP identities are unique keys | TODO | YourCompany.OLTP.RecordsManagement.Persistence (+1642 lines) |
| 4|🧱: OLTP LINQ may be useful | TODO | YourCompany.OLTP.RecordsManagement.Persistence.Linq (+59 lines) |
| 5|🧱: OLTP switch to chassis | TODO | YourCompany.OLTP.RecordsManagement (+1 lines) YourCompany.OLTP.RecordsManagement.DI (+122 lines) YourCompany.OLTP.RecordsManagement.Persistence (-26 lines) YourCompany.OLTP.RecordsManagement.UseCases (-117 lines) YourCompany.OLTP.StateOwnership (+6 lines) |
| 5|🧱: OLTP DI ScopedRecordsProvider | TODO | YourCompany.OLTP.StateOwnership.Reflection.DI (+120 lines) |
| 5|🧱: OLTP DI ScopedUseCasesProvider | TODO | YourCompany.OLTP.RecordsManagement.UseCases.Reflection.DI (+69 lines) |
| 5|🧱: OLTP DI inheritance free repo | TODO | YourCompany.OLTP.RecordsManagement.DI (+444 lines) |
Files: 61 | Lines: 5872
Pros: reduced public surface and boilerplate, no all-in-one inheriting, jobs segregated, maintain your chassis separately
Cons: still requires repository per entity, lacks DI, events, transactional composition (domain modularity), persistence
| Log | Examples | Modules |
|---|---|---|
| 1|🏠: the heart of OLTP is transaction | TODO | YourCompany.OLTP.StateOwnership (+371 lines) |
| 2|🏠: OLTP transaction is limited size | TODO | YourCompany.OLTP.RecordsManagement (+1500 lines) |
| 2|🧱: StructHelper | TODO | YourCompany.CompilerServices (+18 lines) |
| 2|🧱: AwaitTasksList | TODO | YourCompany.Threading (+49 lines) |
| 3|🏠: generic OLTP use cases | TODO | YourCompany.OLTP.RecordsManagement.UseCases (+212 lines) |
| 3|🧱: OLTP transaction structure | TODO | YourCompany.OLTP.RecordsManagement (+1918 lines) |
| 4|🏠: enumerate OLTP use cases | TODO | YourCompany.OLTP.RecordsManagement.UseCases (+117 lines) |
| 4|🧱: OLTP identities are unique keys | TODO | YourCompany.OLTP.RecordsManagement.Persistence (+1642 lines) |
| 4|🧱: OLTP LINQ may be useful | TODO | YourCompany.OLTP.RecordsManagement.Persistence.Linq (+59 lines) |
| 5|🧱: OLTP switch to chassis | TODO | YourCompany.OLTP.RecordsManagement (+1 lines) YourCompany.OLTP.RecordsManagement.DI (+122 lines) YourCompany.OLTP.RecordsManagement.Persistence (-26 lines) YourCompany.OLTP.RecordsManagement.UseCases (-117 lines) YourCompany.OLTP.StateOwnership (+6 lines) |
Files: 56 | Lines: 5508
Pros: clarified identities and streamlined persistence implementation
Cons: may be not enough organized if you need to reuse some use cases
| Log | Examples | Modules |
|---|---|---|
| 1|🏠: the heart of OLTP is transaction | TODO | YourCompany.OLTP.StateOwnership (+371 lines) |
| 2|🏠: OLTP transaction is limited size | TODO | YourCompany.OLTP.RecordsManagement (+1500 lines) |
| 2|🧱: StructHelper | TODO | YourCompany.CompilerServices (+18 lines) |
| 3|🧱: OLTP transaction structure | TODO | YourCompany.OLTP.RecordsManagement (+1918 lines) |
| 4|🧱: OLTP identities are unique keys | TODO | YourCompany.OLTP.RecordsManagement.Persistence (+1642 lines) |
| 4|🧱: OLTP LINQ may be useful | TODO | YourCompany.OLTP.RecordsManagement.Persistence.Linq (+59 lines) |
Files: 47 | Lines: 4167
Pros: reuse authorizers, externalize records batch configuration, customize state access
Cons: still a lot of methods for persistence and complex records batch state
| Log | Examples | Modules |
|---|---|---|
| 1|🏠: the heart of OLTP is transaction | TODO | YourCompany.OLTP.StateOwnership (+371 lines) |
| 2|🏠: OLTP transaction is limited size | TODO | YourCompany.OLTP.RecordsManagement (+1500 lines) |
| 2|🧱: AwaitTasksList | TODO | YourCompany.Threading (+49 lines) |
| 3|🏠: generic OLTP use cases | TODO | YourCompany.OLTP.RecordsManagement.UseCases (+212 lines) |
| 3|🧱: OLTP transaction structure | TODO | YourCompany.OLTP.RecordsManagement (+1918 lines) |
| 4|🏠: enumerate OLTP use cases | TODO | YourCompany.OLTP.RecordsManagement.UseCases (+117 lines) |
Files: 42 | Lines: 3789
Pros: have all control structured in one place
Cons: mixes use case related logic with persistence
| Log | Examples | Modules |
|---|---|---|
| 1|🏠: the heart of OLTP is transaction | TODO | YourCompany.OLTP.StateOwnership (+371 lines) |
| 2|🏠: OLTP transaction is limited size | TODO | YourCompany.OLTP.RecordsManagement (+1500 lines) |
| 3|🧱: OLTP transaction structure | TODO | YourCompany.OLTP.RecordsManagement (+1918 lines) |
Files: 26 | Lines: 1871
Pros: enough to standardize use cases or "service 🙈" layer
Cons: repositories implemented per record type are too big
| Log | Examples | Modules |
|---|---|---|
| 1|🏠: the heart of OLTP is transaction | TODO | YourCompany.OLTP.StateOwnership (+371 lines) |
| 2|🏠: OLTP transaction is limited size | TODO | YourCompany.OLTP.RecordsManagement (+1500 lines) |
Files: 10 | Lines: 637
Pros: not tied to typical component types, the most common
Cons: you may find another set of conventions more suitable
| Log | Examples | Modules |
|---|---|---|
| 1|🧱: basic configurations covered | TODO | YourCompany.Configuration (+637 lines) |
Files: 6 | Lines: 371
Pros: isolate your model from anything unrelated to your domain
Cons: too much boilerplate code being copied for each use case
| Log | Examples | Modules |
|---|---|---|
| 1|🏠: the heart of OLTP is transaction | TODO | YourCompany.OLTP.StateOwnership (+371 lines) |
Files: ### | Lines: #####
Pros: why do you choose this entry point
Cons: why it might be not enough for you
| Log | Examples | Modules |
|---|---|---|
| replace_with_each_included_commit_subject | at‑least‑one‑example‑solution‑name extra‑example‑solution‑name |
YourCompany.Framework.Assembly.Name1 (+diff lines) YourCompany.Framework.Assembly.Name2 (-diff lines) YourCompany.Framework.Assembly.NameN (0 lines) |
The table above is written by the script while staying on a break during
the rebase: it reads the branch bound by the break from the rebase todo and
regenerates the whole block from the markers around it. Pros and cons are
left as authored, they are not derivable from the commits.
Both this and the commit logs script run from a single alias invoked before each break, in that order.
👇 Replaced or appended in ordered manner by the script.
|
6 files changed, 371 insertions(+) One atomic action. Heard about DDD "Aggregates"? These are classes Typical transactions modeled consist of one or many modifying actions. The mistake № 1 is to model aggregates over abilities and limitations The model accepts its record data's In transition
As mentioned above we expanded ISpecification purpose to become Finally, still keeping the DDD book open, what is an entity? Precisely, digging more into the concept of entity, how do you Down the road we'll see how identities are represented and managed |
|
10 files changed, 637 insertions(+)
As of plugins - one decision point is being "collectible". It's not |
|
20 files changed, 1500 insertions(+) Long story short big transactions work bad. We need a way But the size is not the only "specification" to be considered. Considering the compatibility rules and their nested long-name nature Among all it's worth to highlight use cases and keyset pagination. For use cases as we stated before it is typical to modify data. For keyset pagination. It tightly relates to records ordering. To be The model asks a particular factory to provide a key |
|
1 file changed, 18 insertions(+) |
|
1 file changed, 49 insertions(+) |
|
1 file changed, 57 insertions(+) |
|
1 file changed, 31 insertions(+) |
|
2 files changed, 143 insertions(+) |
|
1 file changed, 26 insertions(+) |
|
11 files changed, 681 insertions(+) Firstly it supports both As of Also there is For demo provider plugins we've chosen PostgreSQL and Sqlite. |
|
7 files changed, 328 insertions(+) |
|
1 file changed, 106 insertions(+) |
|
4 files changed, 263 insertions(+) |
|
2 files changed, 212 insertions(+) Easily reuse and combine authorizers, record property setters or |
|
2 files changed, 176 insertions(+) |
|
17 files changed, 1919 insertions(+), 1 deletion(-) Be ready to implement following sequence per each record type:
Including a bunch of virtual methods, these give you ability to pause |
|
2 files changed, 87 insertions(+) |
|
36 files changed, 2464 insertions(+), 2 deletions(-) This one is very missing out-of-the-box in EFCore. This replaces the Another covered problem is database strings collation having no analog |
|
2 files changed, 117 insertions(+) We've segregated use case related concerns into several interfaces. The set of methods to override is slightly reduced for
If your concern is reducing the number of methods and/or simplifying
|
|
11 files changed, 1642 insertions(+) These might be primary, natural, or... prefixed. Remember afterId? The mistake № 2 is to expose generated sequential ids, store, The mistake № 3 is to violate aggregate boundaries by putting extra UniqueKey semi-closed hierarchy takes into account all of these As for
These might be still not desired. You may find more useful the
|
|
2 files changed, 59 insertions(+) It's a small extension to the streamlined data access interfaces |
|
10 files changed, 790 insertions(+), 1 deletion(-) |
|
1 file changed, 63 insertions(+) |
|
11 files changed, 764 insertions(+), 1 deletion(-) |
|
1 file changed, 45 insertions(+) |
|
4 files changed, 112 insertions(+), 1 deletion(-) |
|
7 files changed, 347 insertions(+) An edge case of the topology is all the entity properties. |
|
35 files changed, 298 insertions(+), 312 deletions(-) Here we internalize a lot of public classes and methods previously This allow us to switch into much more powerful approaches while Note that |
|
4 files changed, 120 insertions(+) |
|
1 file changed, 69 insertions(+) |
|
8 files changed, 445 insertions(+), 1 deletion(-) You never need to implement it anymore since your record's
Just call |
|
21 files changed, 2256 insertions(+) This is a basic Here we also introduce |
|
19 files changed, 1146 insertions(+), 38 deletions(-) This is a modifying finalization for the previously implemented record Worth mentioning that by extending its responsibility we're actually Furthermore, to not keep silent about this, we're switching to the |
|
9 files changed, 323 insertions(+), 2 deletions(-) This entry point benefits from the plugin based EFCore initialization As of the huge gap in lines with the previous entry point we can
|