Ultra fast multi threads/tasks .Net Database framework.
Norm is stands for Not an ORM is a C# lib for very HIGH Speed DB data processing in async way with immediately operations and at background with Processing data with Batches. It at least 10 times faster then EF/EF.Core. In Comparison to ORMs Norm has following disadvantages:
- No object tracking
- No Lazy loading properties
But it gives us the following:
- Read spead is fast (10000 rows select from 100000 rows Mysql database ~100-200 ms)
| Table size (rows) | Rows to select | Time, ms |
|---|---|---|
| 100k | 10k | 154 |
| 100k | 10k in a middle | 190 |
| 100k | 100k | 1114 |
| 1M | 100k | 1135 |
| 1M | 500k | 5624 |
- Insert speed is fast (10000 rows ~ 600 ms, 100000 rows ~ 3000-5000 ms on
i5CPU forMySql 8.0.23with default settings)
| Rows to insert | Time, ms |
|---|---|
| 100 | 13 |
| 1000 | 62 |
| 10000 | 549 |
| 100000 | 5111 |
- Can work with DB in multiple threads unlike do all
ORMs - Support
BULKoperations - Can synchronize data in background (for quite big operations, truly
asyncbehavior) - Can be used in
CQRSapproach because works in own thread and uses multiple tasks. - All modification operations (
Create,UpdateandDelete) are usingDB Transactions.
Norm works with persistant entities (table mapping or aggregate to multiple tables) via Repository interface IDbRepository<T> (T is a generic type of persistant object, i.e. User). Norm has following implementation of IDbRepository<T> interface:
MySqlBufferedRepository<T>forMySqlDB server, it implementsBufferedDbRepository<T>SqlServerBufferedRepository<T>forSqlServerDB server, it implementsBufferedDbRepository<T>PostgresBufferedRepository<T>forPostgresDB server, it implementsBufferedDbRepository<T>SqLiteBufferedRepository<T>forSqLiteDB server, it implementsBufferedDbRepository<T>
Consider how to use it on MySql Db:
- Add the appropriate package; see the section below
- Create a
IDbRepository<T>instance as follows:
DbRepositorySettings dbRepositorySettings = new DbRepositorySettings()
{
BufferThreshold = 100,
CommandTimeout = 120,
BufferSynchronizationDelayTimeout = 100,
ForceSynchronizationBufferDelay = 500
};
IDbRepository<PhysicalValueEntity> repo = new MySqlBufferedRepository<PhysicalValueEntity>(ConnectionString, dbRepositorySettings,
new PhysicalValueQueryBuilder(),
PhysicalValueFactory.Create, new NullLoggerFactory());Contructor expect following params:
- DB connection string
- Repository settings:
BufferThresholdsize of buffer (creainge or updainge entities) to syncTimeoutof executing command in secondsBufferSynchronizationDelayTimeouttime in ms between background synchronization iterations attemptsForceSynchronizationBufferDelaytimeout for sync if amount of items to create/update < BufferThreshold
- query builder that implements interface
IDbEntityQueryBuilder<TE>(see example in tests) - factory that builds Entity from array of column values (see also tests)
- logger factory
- Read Entities 3.1 Without filtering
IList<PhysicalValueEntity> items = await repo.GetManyAsync(page, size, new List<WhereParameter>(), null);3.2 With filtering
IList<PhysicalValueEntity> items = await repo.GetManyAsync(page, size, new List<WhereParameter>()
{
new WhereParameter("id", null, false, WhereComparison.Greater, new List<object>(){lowerIdValue}, false),
new WhereParameter("id", WhereJoinCondition.And, false, WhereComparison.Less, new List<object>(){upperIdValue}, false)
}, null);- Create Entity 4.1 Single
PhysicalValueEntity entity = new PhysicalValueEntity()
{
Id = id,
Name = "new phys value",
Description = "new phys value",
Designation = "NPV"
};
bool result = await repo.InsertAsync(entity, true);The last insert method param is responsible for inserting into the Repository task in the background if false or immediately if true 4.2 Bulk
IList<PhysicalValueEntity> newPhysValues = new List<PhysicalValueEntity>()
{
new PhysicalValueEntity()
{
Id = 30,
Name = "new phys value",
Description = "new phys value",
Designation = "NPV"
},
new PhysicalValueEntity()
{
Id = 31,
Name = "new phys value2",
Description = "new phys value2",
Designation = "NPV2"
},
new PhysicalValueEntity()
{
Id = 32,
Name = "new phys value3",
Description = "new phys value3",
Designation = "NPV3"
}
};
int result = await repo.BulkInsertAsync(newPhysValues, true);- Update and bulk update are analogous to create methods:
- Delete is quite a simple:
bool result = await repo.DeleteAsync(new List<WhereParameter>()
{
new WhereParameter("id", null, false, WhereComparison.Equal, new List<object>(){newPhysValue.Id})
});