What we will build you can see here :
Each class will have it is own CodeTemplates\EFCore templates from which will generate the code.
Let’s start with ExampleModels : Here will be the class definitions . From the table defintion , the DB2Code will generate
1. A definition of a interface with table columns as properties
public interface I_Department_Table
{
long IDDepartment { get; set; }
string Name { get; set; }
}
2. A class with relationships
public partial class Department
{
[Key]
public long IDDepartment { get; set; }
[StringLength(50)]
[Unicode(false)]
public string Name { get; set; } = null!;
[InverseProperty("IDDepartmentNavigation")]
public virtual ICollection<Employee> Employee { get; } = new List<Employee>();
}
3. class without relationship
public class Department_Table : I_Department_Table
{
public long IDDepartment { get; set; }
public string Name { get; set; }
}
4. Explicit operator to convert 2 to 3
public static explicit operator Department_Table?(Department obj) {
if(obj == null)
return null;
//System.Diagnostics.Debugger.Break();
var ret= new Department_Table();
ret.CopyFrom(obj as I_Department_Table );
return ret;
}
public static explicit operator Department?(Department_Table obj) {
if(obj == null)
return null;
//System.Diagnostics.Debugger.Break();
var ret= new Department();
ret.CopyFrom(obj as I_Department_Table) ;
return ret;
}
5. Public method CopyFrom( interface)
public void CopyFrom(I_Department_Table other) {
this.IDDepartment = other.IDDepartment;
this.Name = other.Name;
}
5. Enum with name of the columns
public enum eDepartmentColumns {
None = 0
,IDDepartment
,Name
}
6. Metadata with name of the tables and the columns
public static MetaTable metaData = new("Department");
static Department_Table (){
MetaColumn mc=null;
mc=new ("IDDepartment","long",false);
metaData.AddColumn(mc);
mc=new ("Name","string",false);
metaData.AddColumn(mc);
}
Now it comes ExampleContext . Here will the database context and various search definitions that you need (e.g. for a column of type int, search will generate = , > , < , between , in array ) . More , it will generate metadata for the tables that are part of the context.
public IAsyncEnumerable<Department> DepartmentSimpleSearch(GeneratorFromDB.SearchCriteria sc, eDepartmentColumns colToSearch, string value){}
public IAsyncEnumerable<Department> DepartmentGetAll(){}
public async Task<Department[]> DepartmentFind_Array( SearchDepartment? search){}
public Task<long> DepartmentCount( SearchDepartment search)
Now it comes ExampleControllers . This will generate controllers for REST API for the table and also Search Controllers for any kind of search that you may want.
//this is the REST controller
[ApiController]
[Route("[controller]")]
public partial class RESTDepartmentController : Controller
{
private ApplicationDBContext _context;
public RESTDepartmentController(ApplicationDBContext context)
{
_context=context;
}
[HttpGet]
public async Task<Department_Table[]> Get(){
var data= await _context.Department.ToArrayAsync();
var ret = data.Select(it => (Department_Table)it!).ToArray();
return ret;
}
[HttpGet("{id}")]
public async Task<ActionResult<Department_Table>> GetDepartment(long id)
{
if (_context.Department == null)
{
return NotFound();
}
var item = await _context.Department.FirstOrDefaultAsync(e => e.IDDepartment==id);
if (item == null)
{
return NotFound();
}
return (Department_Table)item!;
}
[HttpPatch("{id}")]
public async Task<IActionResult> PutDepartment(long id, Department value)
{
if (id != value.IDDepartment)
{
return BadRequest();
}
_context.Entry(value).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!DepartmentExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
[HttpPost]
public async Task<ActionResult<Department>> PostDepartment(Department_Table value)
{
var val = new Department();
val.CopyFrom(value);
_context.Department.Add(val);
await _context.SaveChangesAsync();
return CreatedAtAction("GetDepartment", new { id = val.IDDepartment }, val);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteDepartment(long id)
{
if (_context.Department == null)
{
return NotFound();
}
var item = await _context.Department.FirstOrDefaultAsync(e => e.IDDepartment==id);
if (item == null)
{
return NotFound();
}
_context.Department .Remove(item);
await _context.SaveChangesAsync();
return NoContent();
}
private bool DepartmentExists(long id)
{
return (_context.Department.Any(e => e.IDDepartment == id));
}
}
And also a SEARCH controller
[ApiController]
[Route("[controller]/[action]")]
public partial class AdvancedSearchDepartmentController : Controller
{
private ISearchDataDepartment _search;
public AdvancedSearchDepartmentController(ISearchDataDepartment search)
{
_search=search;
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> GetAll()
{
await foreach(var item in _search.DepartmentFind_AsyncEnumerable(null))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> GetWithSearch(SearchDepartment s)
{
await foreach(var item in _search.DepartmentFind_AsyncEnumerable(s))
{
yield return (Department_Table)item!;
}
}
//has one key
[HttpGet]
public async Task<Department_Table?> GetSingle(long id){
var data=await _search.DepartmentGetSingle(id);
if(data == null)
return null;
return (Department_Table)data;
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> EqualValues_IDDepartment( long[] values)
{
string? value=null;
if(values.Length>0)
value=string.Join( ",",values);
var sc=SearchDepartment.FromSearch(GeneratorFromDB.SearchCriteria.InArray,eDepartmentColumns.IDDepartment,value);
await foreach (var item in _search.DepartmentFind_AsyncEnumerable(sc))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> DifferentValues_IDDepartment( long[] values)
{
string? value=null;
if(values.Length>0)
value=string.Join( ",",values);
var sc=SearchDepartment.FromSearch(GeneratorFromDB.SearchCriteria.NotInArray,eDepartmentColumns.IDDepartment,value);
await foreach (var item in _search.DepartmentFind_AsyncEnumerable(sc))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> EqualValue_IDDepartment( long value)
{
var sc = GeneratorFromDB.SearchCriteria.Equal;
await foreach (var item in _search.DepartmentSimpleSearch_IDDepartment(sc, value))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> DifferentValue_IDDepartment( long value)
{
var sc = GeneratorFromDB.SearchCriteria.Different;
await foreach (var item in _search.DepartmentSimpleSearch_IDDepartment(sc, value))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> SimpleSearch_IDDepartment(GeneratorFromDB.SearchCriteria sc, long value){
await foreach(var item in _search.DepartmentSimpleSearch_IDDepartment(sc,value))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> FindNull_IDDepartment(){
var sc = GeneratorFromDB.SearchCriteria.Equal;
await foreach(var item in _search.DepartmentSimpleSearchNull_IDDepartment(sc))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> FindNotNull_IDDepartment(){
var sc = GeneratorFromDB.SearchCriteria.Different;
await foreach(var item in _search.DepartmentSimpleSearchNull_IDDepartment(sc))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> EqualValues_Name( string[] values)
{
string? value=null;
if(values.Length>0)
value=string.Join( ",",values);
var sc=SearchDepartment.FromSearch(GeneratorFromDB.SearchCriteria.InArray,eDepartmentColumns.Name,value);
await foreach (var item in _search.DepartmentFind_AsyncEnumerable(sc))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> DifferentValues_Name( string[] values)
{
string? value=null;
if(values.Length>0)
value=string.Join( ",",values);
var sc=SearchDepartment.FromSearch(GeneratorFromDB.SearchCriteria.NotInArray,eDepartmentColumns.Name,value);
await foreach (var item in _search.DepartmentFind_AsyncEnumerable(sc))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> EqualValue_Name( string value)
{
var sc = GeneratorFromDB.SearchCriteria.Equal;
await foreach (var item in _search.DepartmentSimpleSearch_Name(sc, value))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> DifferentValue_Name( string value)
{
var sc = GeneratorFromDB.SearchCriteria.Different;
await foreach (var item in _search.DepartmentSimpleSearch_Name(sc, value))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> SimpleSearch_Name(GeneratorFromDB.SearchCriteria sc, string value){
await foreach(var item in _search.DepartmentSimpleSearch_Name(sc,value))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> FindNull_Name(){
var sc = GeneratorFromDB.SearchCriteria.Equal;
await foreach(var item in _search.DepartmentSimpleSearchNull_Name(sc))
{
yield return (Department_Table)item!;
}
}
[HttpGet]
public async IAsyncEnumerable<Department_Table> FindNotNull_Name(){
var sc = GeneratorFromDB.SearchCriteria.Different;
await foreach(var item in _search.DepartmentSimpleSearchNull_Name(sc))
{
yield return (Department_Table)item!;
}
}
}//end class
Finally , ExampleWebAPI . This will add the controllers from the ExampleControllers to show the use .
var assControllers = typeof(UtilsControllers).Assembly;
builder.Services.AddControllers()
.PartManager.ApplicationParts.Add(new AssemblyPart(assControllers)); ;
Of course , the name Example will be replaced , from the template, with the name of your project