Db2Code–part 2- architecture
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
Leave a Reply