com.techienetworks.framework
2.1.12
dotnet add package com.techienetworks.framework --version 2.1.12
NuGet\Install-Package com.techienetworks.framework -Version 2.1.12
<PackageReference Include="com.techienetworks.framework" Version="2.1.12" />
<PackageVersion Include="com.techienetworks.framework" Version="2.1.12" />
<PackageReference Include="com.techienetworks.framework" />
paket add com.techienetworks.framework --version 2.1.12
#r "nuget: com.techienetworks.framework, 2.1.12"
#:package com.techienetworks.framework@2.1.12
#addin nuget:?package=com.techienetworks.framework&version=2.1.12
#tool nuget:?package=com.techienetworks.framework&version=2.1.12
TNFramework
A simple, effective, object-oriented ORM.
Getting Started
The Techie Framework is designed to be used as a platform to get your .net enterprise application off the group and running, fast. Currently, only SQL server is supported with c# output.
The "Framework" part of this framework is the data access layer and the business object definition. Everything else is just simple generated code with a few utility functions to make my coding life easier and faster.
Prerequisites
The prerequisite to starting with the Techie Framework is a well defined, well connected SQL server database design. There are a few rules and features of the framework that will help you along the way.
Database Design
Use the following loosly defined rules to start using the framework.
Table Names
All table names should be singular, with or without a prefix. Example table names are:
User
Address
Customer
Order
...
with a prefix
TNUser
TNAddress
TNCustomer
Primary Keys
All tables must have a primary key, either varchar, int, bigint or uniqueidentifier. Running the code generator against a table without a primary key will yield weird results. This field name ideally should be the table name + "ID". In all cases, the first column of the table is assumed to be the primary key for the table.
OrderID
UserID
AddressID
Foreign Keys
Tables linked via foreign key must have the primary key in the field name to create an object link. For example, a link from an "Order" table to an "Address" table would look like:
ShippingAddressID
Indexes
Tables with an index will allow the generator to create stored procedures that can be used with those indexes. For example, an Order table with a column called CustomerID which is a FK and, has an Index would create a stored procedure called
getOrderByCustomerID
If multiple columns are present in an index, then the stored procedure would be
getOrderByFirstColumnSecondColumn
Cross References
Cross reference tables should always have an Primary Key, and end with the verb "Xref". These tables are ignored by the generator and only stored procedures are created for you to define the cross reference manually.
Type Codes
Columns that end with the verb "TypeID" will cause the generator to spit out Enum files so that an actual enumerator can be used in your code. However, if a table exists with that type then this will not occur as it will be assumed that the types will be defined by data instead.
StatusCodes
By adding a column names "StatusCodeID", the generator will spit out a Status enum for you to define the status in code. a column called StatusCodeID in an Order table will yield the enumn OrderStatus and create the enum property on the order object.
DateCreated
By adding a column named "DateCreated" will tell the generator to default the field in the class to DateTime.Now.
LastUpdated
Same as DateCreated, except this column will always default to DateTime.Now when a save is called on the object.
Inheritance
This is an experimental feature. By defining a foreign key column with a suffix of IID, you tell the framework that the object is derived from another object. The intention of this is to allow for inheritance of objects with data layer persistance.
For example an "Transaction" table might be used for financial history, with a transactionType column that defines what kind of transaction it was - such as an payment or a refund. By creating a "Refund" table that has a column "TransactionIID" the class generated for the Refund will derive from the Transaction table.
Timestamps
If a table contains a timestamp column, the framework will handle concurrency issues around that and not allow updates to stale objects.
Calculated Columns
Calculated columns are ignored by the generator, and will not be included in the object.
Code Generation
The Techie.Tools.CodeGenerator object is the class to use to invoke generation of objects from a datable. Typically this would look something like
public static void Main()
{
CodeGenerator codeGenerator = new CodeGenerator();
codeGenerator.ConnectionString = "Server=<SOMESERVER>;Database=<SOMEDATABASE>;Integrated Security=true";
codeGenerator.OutputPath = "c:\\temp";
codeGenerator.ShouldCreateProcedures = true;
codeGenerator.TargetNamespace = "Techie.ApplicationName";
codeGenerator.Author = "Jaysam Thanki";
codeGenerator.Company = "Techie Networks";
// Optional: Generate DTOs and API Controllers for REST APIs
codeGenerator.ShouldCreateDtos = true;
codeGenerator.ShouldCreateApiControllers = true;
codeGenerator.ShouldCreatePaginationHelpers = true;
codeGenerator.DefaultPageSize = 20;
// Optional: Map database tables to different class names
codeGenerator.TableMapping = new Dictionary<string, string>
{
{ "tbl_users", "User" }, // Database table tbl_users becomes User class
{ "customer_data", "Customer" } // Database table customer_data becomes Customer class
};
// Optional: Map database fields to different property names
codeGenerator.TableFieldMapping = new Dictionary<string, string>
{
{ "User.usr_id", "UserID" }, // Field usr_id in User table becomes UserID property
{ "User.email_addr", "Email" }, // Field email_addr in User table becomes Email property
{ "Customer.cust_name", "Name" } // Field cust_name in Customer table becomes Name property
};
codeGenerator.Log += CodeGenerator_Log;
codeGenerator.Generate();
}
private static void CodeGenerator_Log(string message)
{
Console.WriteLine(message);
}
Make sure your connection string has a user that has permissions to read and write to the database. Only stored procedures will be created, if ShouldCreateProcedures is set to true.
Output
The Code Generator spits out 8 folders.
BaseClasses
The BaseClasses folder generates classes that you simply copy to your Visual Studio project, and forget. Do not modify these files as subsequent future generations would yield new files that would override these files.
UserClasses
The UserClasses folder generates classes ready for you to put your real business logic into, you should copy these files ONCE to your project, and then make modifications to them as needed.
BaseDtos
The BaseDtos folder generates base Data Transfer Object classes that are used for REST APIs. Do not modify these files as subsequent future generations would yield new files that would override these files.
Dtos
The Dtos folder generates DTO classes that inherit from BaseDtos. These are ready for you to customize with additional properties or methods. Copy these files ONCE to your project, and then make modifications to them as needed.
ApiControllers
The ApiControllers folder generates REST API controllers with standard CRUD operations for each business object. These controllers use the generated DTOs and include pagination support where applicable. Copy these files ONCE to your project, and then make modifications to them as needed.
TypeCodes
The TypeCodes folder generates enumerations for your type codes ready for population. You should copy these files ONCE to your project, and then make modifications to them as needed.
StatusCodes
The StatusCodes folder generates enumerations for your type codes ready for population. You should copy these files ONCE to your project, and then make modifications to them as needed.
Database
Individual files are created for each stored procedure, and a single Create.sql for all of them. If you have a change process you may want to include the create.sql for each build/deployment to ensure the correct procedures are in the system
REST API Support
When DTOs and API Controllers are generated, the framework provides full REST API support:
Generated API Endpoints
For each business object, the following endpoints are created:
GET /api/{object}
- Get all records (with pagination support)GET /api/{object}/{id}
- Get a single record by IDPOST /api/{object}
- Create a new recordPUT /api/{object}/{id}
- Update an existing recordDELETE /api/{object}/{id}
- Delete a record
Pagination
When pagination helpers are enabled, list endpoints support:
?page=1&pageSize=20
- Query parameters for pagination- Response includes total count and pagination metadata
DTOs vs Business Objects
- DTOs (Data Transfer Objects) are lightweight objects for API communication
- They exclude sensitive fields and complex object relationships
- BaseDtos contain auto-generated properties from database columns
- User DTOs can be extended with custom properties and computed fields
Working with Existing Database Schemas
When working with databases where you don't control the schema, the CodeGenerator provides mapping features to handle non-standard naming conventions:
Table Name Mapping
Use the TableMapping
dictionary to map database table names to class names during code generation:
codeGenerator.TableMapping = new Dictionary<string, string>
{
{ "tbl_users", "User" }, // tbl_users table → User class
{ "customer_data", "Customer" }, // customer_data table → Customer class
{ "legacy_orders", "Order" } // legacy_orders table → Order class
};
Field Name Mapping
Use the TableFieldMapping
dictionary to rename database columns to property names. The key format is "TableName.FieldName":
codeGenerator.TableFieldMapping = new Dictionary<string, string>
{
{ "User.usr_id", "UserID" }, // usr_id column → UserID property
{ "User.email_addr", "Email" }, // email_addr column → Email property
{ "Customer.cust_name", "Name" }, // cust_name column → Name property
{ "Order.ord_date", "OrderDate" } // ord_date column → OrderDate property
};
These mappings are applied during code generation, so the generated classes will use your preferred naming conventions while still mapping correctly to the underlying database schema. This is particularly useful when:
- Working with legacy databases with non-standard naming conventions
- Integrating with third-party databases you don't control
- Migrating from other ORMs that used different naming standards
- Following specific coding standards that differ from database conventions
Business Object Class
The Techie.BusinessObject class is the heart of the system. Here are a few things you can use from it
Create a custom constructor
Imagine a "User" class, and you want to look up a user by their email address rather than their Primary Key ID.
public User(string emailAddress)
: base()
{
IDbCommand command = this.MakeCommand("getUserByEmailAddress");
this.AddParam(command, "@EmailAddress", DbType.String, emailAddress);
this.PopulateObject(command);
}
In just three lines, you can return an object by using new User("junk@techie.org") that is fully populated and ready to go. If the user does not exist with that email, the constructor simply returns an empty object, so be sure to check for a UserID>0 or UserId != Guid.Empty depending upon how your PK's are defined.
Logging
Each derived class gets its own Log4Net object, so simply use Log.Whatever wherever you need logging.
ToJson
Each derived class has the option to output a Json of itself using the ToJson method
GetDifferences
This method takes in a destination object and returns a string formatted with the difference between itself and the object in the parameter.
DataSource
You may run into a situation whereby the object being created is pysically stored in a seperate database, such as image binaries or other large blobs you do not want to pollute your production data. By specifying the datasource in the generator the classes will be Decorated with a [DataSouce("CONNECTIONSTRINGKEY")] attribute so that the data access layer knows where to get/set data.
Contact
Please contact me via www.techienetworks.com if you require assistance in getting this going, or if you have a project that needs worked on using TNFramework.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- log4net (>= 3.1.0)
- Microsoft.Azure.Cosmos (>= 3.52.1)
- Microsoft.Data.SqlClient (>= 6.1.0)
- Microsoft.Extensions.Configuration.Json (>= 9.0.7)
- Microsoft.SqlServer.Types (>= 160.1000.6)
- Newtonsoft.Json (>= 13.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last Updated |
---|---|---|
2.1.12 | 192 | 8/13/2025 |
2.1.11 | 133 | 8/11/2025 |
2.1.10 | 194 | 8/11/2025 |
2.1.9 | 124 | 8/3/2025 |
2.1.8 | 99 | 7/29/2025 |
2.1.7 | 97 | 7/29/2025 |
2.0.6 | 520 | 7/21/2025 |
2.0.4 | 476 | 7/21/2025 |
2.0.0 | 133 | 7/18/2025 |
1.4.9 | 251 | 5/19/2025 |
1.4.8 | 428 | 3/4/2025 |
1.4.7 | 222 | 3/4/2025 |
1.4.6 | 215 | 3/4/2025 |
1.4.5 | 214 | 3/4/2025 |
1.4.4 | 191 | 2/7/2025 |
1.4.3 | 172 | 2/2/2025 |
1.4.2 | 114 | 2/1/2025 |
1.4.1 | 85 | 1/15/2025 |
1.4.0 | 394 | 1/3/2025 |
1.3.6 | 576 | 10/8/2024 |
1.3.5 | 129 | 8/2/2024 |
1.3.4 | 838 | 7/5/2024 |
1.3.3 | 153 | 6/11/2024 |
1.3.1 | 2,098 | 10/19/2023 |
1.3.0 | 190 | 10/16/2023 |
1.2.11 | 1,665 | 10/19/2023 |
1.2.10 | 216 | 10/10/2023 |
1.2.9 | 358 | 6/23/2023 |
1.2.8 | 264 | 6/16/2023 |
1.2.7 | 250 | 6/16/2023 |
1.2.6 | 601 | 5/18/2023 |
1.2.5 | 500 | 11/11/2022 |
1.2.4 | 1,140 | 10/6/2022 |
1.2.3 | 629 | 9/13/2022 |
1.2.2 | 1,290 | 11/9/2021 |
1.2.1 | 485 | 7/23/2021 |
1.2.0 | 634 | 6/4/2021 |
1.1.8 | 1,180 | 11/10/2021 |
1.1.7 | 500 | 11/10/2021 |
1.1.6 | 493 | 11/10/2021 |
1.1.5 | 2,041 | 12/18/2019 |
1.1.4 | 797 | 4/19/2019 |
1.1.3 | 772 | 3/11/2019 |
1.1.2 | 796 | 3/7/2019 |
1.1.1 | 856 | 2/18/2019 |
1.1.0 | 849 | 2/17/2019 |
1.0.0 | 829 | 2/5/2019 |