Web tabanlı uygulamalarda ve genel olarak özel yazılımların hazırlanmasında, yazılım mimarisinin oluşturulması zaman alıcı bir süreç olarak karşımıza çıkmaktadır. Hazır ve güncel bir yazılım altyapısına sahip olanlar için ise bu süreç önemli ölçüde kısalır.

Form yapıları için arka planda SQL'leri oluşturan bir C# kütüphanesi, HTML5/Bootstrap ile sayfa tasarımı, saf JavaScript ile ön yüz kodlaması, Ajax 2 ve JSON ile veri transferi, arka planda Razor ve PageModel ile iş mantığı — bunların tamamını barındıran hazır bir şablon sizin için anlamlıysa bu yazıyı okumanızda fayda vardır.

SELECT, INSERT, UPDATE, DELETE SQL DML komutları kodlamanın önemli bir bölümünü oluşturur. Bu DML kodlarını otomatik olarak hazırlayan bir kütüphane — sdbcsapi — işleri oldukça kolaylaştırmaktadır.

C# — Veritabanı Sorgu İşlemi

Bir C# kodundaki select işlemini yapan kod parçası aşağıda görünüyor.

C# — tableAction / selectData
// For executing database query operations
dbQuery = p.executeTable.tableAction(p.action, p.formData, p.prepareQuery);

if (dbQuery)
    // If query is true get table data from api
    p.tableData = (string[][])p.executeTable.selectData(p.dataType);
else
    errorString = p.executeTable.getErrorString();

Razor — HTML Form Tasarımı

Razor kodunda HTML sayfa tasarımında formlarımız aşağıdaki gibi olabilir.

Razor — Yeni Kayıt Formu
@(new HtmlString(Model.menuString))

<div class="container-fluid">
    <div class="row">
        @(new HtmlString(Model.leftSideStr))
        <div class="col-md-11 col-xl-10">
            <a href="#yeniK" class="btn btn-outline-dark" data-toggle="collapse">
                Yeni @Model.pageTitle
            </a>
            <form id="yeniK" class="form collapse" enctype="multipart/form-data" method="post">
                <datalist id="paths"></datalist>
                <datalist id="types"></datalist>
                <datalist id="codes"></datalist>
                <div class="form-group">
                    <table class="table table-borderless">
                        <tbody>
                            <tr>
                                <td><label for="y_1">@Model.labelNames[1]:</label></td>
                                <td>
                                    <input type="@Model.inputTypes[1]"
                                           class="form-control form-control-sm"
                                           name="@Model.fieldNames[1]" id="y_1"
                                           placeholder="@Model.labelNames[1] giriniz." required>
                                </td>
                                <td><label for="y_2">@Model.labelNames[2]:</label></td>
                                <td>
                                    <input type="@Model.inputTypes[2]"
                                           class="form-control form-control-sm"
                                           name="@Model.fieldNames[2]" id="y_2"
                                           placeholder="@Model.labelNames[2] giriniz."
                                           list="paths" required>
                                </td>
                            </tr>
                            <tr>
                                <td><label for="y_4">Kod:</label></td>
                                <td>
                                    <input type="file" class="form-control form-control-sm"
                                           name="@Model.fileField" id="y_4" required
                                           onchange="fileNameInfo('y_4','y_1')">
                                </td>
                            </tr>
                            <tr>
                                <td>
                                    <button type="button" class="btn btn-outline-info btn-sm"
                                            onclick='sendInsert("@Model.pageName","yeniK")'>
                                        Kaydet
                                    </button>
                                </td>
                                <td>
                                    <button type="reset" class="btn btn-outline-secondary btn-sm">
                                        İptal
                                    </button>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </form>
        </div>
    </div>

Razor — Tablo Bölümü

Sayfamızda tablo bölümü de olacaktır.

Razor — Listeleme Tablosu
<div class="row" id="ldTable">
    <div class="col-md-12">
        <h2>@Model.pageTitle Listesi</h2>
        <div class="table-responsive">
            <table class="table table-striped table-bordered table-sm">
                <thead>
                    <tr>
                        <th>Sıra</th>
                        <th onclick="sortById()">@Model.labelNames[0]</th>
                        <th onclick="sortByProp('@Model.fieldNames[1]')">@Model.labelNames[1]</th>
                        <th onclick="sortByProp('@Model.fieldNames[2]')">@Model.labelNames[2]</th>
                        <th onclick="sortByProp('@Model.fieldNames[3]')">@Model.labelNames[3]</th>
                        <th onclick="sortByDate('@Model.fieldNames[5]', true)">@Model.labelNames[5]</th>
                    </tr>
                </thead>
                <tbody id="listTb"></tbody>
            </table>
        </div>

Razor — Sayfalandırma ve Dışa Aktarım

Sayfalandırma yapısı ve Excel/JSON/CSV/PDF çıktıları için butonlarımız var.

Razor — Sayfalandırma + Dışa Aktarım
<div id="pgnId">
    <ul class="pagination">
        <li>
            @{ var lineCount = Model.sessionBean.getLineCount(); }
            <input id="p_size" type="text" class="form-control form-control-sm"
                   value=@lineCount size=3 onchange="setPage()">
        </li>
        <li>
            <button type="button" class="btn btn-outline-info btn-sm"
                    id="pageO" onclick="getPage('O')">&laquo;</button>
        </li>
        <li><button ... id="page1" onclick="paging(1)" value="1">1</button></li>
        <li><button ... id="page2" onclick="paging(2)" value="2">2</button></li>
        <li><button ... id="page3" onclick="paging(3)" value="3">3</button></li>
        <li><button ... id="page4" onclick="paging(4)" value="4">4</button></li>
        <li><button ... id="page5" onclick="paging(5)" value="5">5</button></li>
        <li>
            <button type="button" class="btn btn-outline-info btn-sm"
                    id="pageS" onclick="getPage('S')">&raquo;</button>
        </li>
        <li><button ... onclick="exportToExcel('@Model.pageTitle'+'List')">Excel</button></li>
        <li><button ... onclick="exportToJson('@Model.pageTitle'+'List')">Json</button></li>
        <li><button ... onclick="exportToCSV('@Model.pageTitle'+'List')">CSV</button></li>
        <li><button ... onclick="exportToPDF('@Model.pageTitle'+'List')">PDF</button></li>
    </ul>
</div>

Razor — Debug Alarm Yapısı

Alarmlarla ilgili kısmı atlamamakta fayda var.

Razor — Debug Alerts
<div id="alerts">
    @if ((Model.tableData == null || Model.tableData.Length == 0) && Model.isDebug)
    {
        <div class="alert alert-warning">
            <strong>tableData</strong> is empty!
            <br /><strong>SQL0:</strong> @Model.qsql
            <br /><strong>SQL1:</strong> @Model.qsql2
        </div>
    }
    @if (Model.errorString != null && Model.errorString.Length > 0 && Model.isDebug)
    {
        <div class="alert alert-danger">
            <strong>errorString:</strong> @Model.errorString
        </div>
    }
    @if (Model.jsObjData != null && Model.jsObjData.Length > 0 && Model.isDebug)
    {
        <div class="alert alert-info">
            <strong>jsObjData:</strong> @Model.jsObjData
            <br />tableData[0][0]: @(Model.tableData != null ? Model.tableData[0][0] : "")
            <br />messageString: @(Model.messageString ?? "")
        </div>
    }
</div>

JavaScript — Başlangıç Değişkenleri

JavaScript başlangıç değişkenleri ve değer ataması Razor sayfası üzerinde yapılır.

Razor + JavaScript — Değişken Başlatma
<script>
  var jsObjData, dataList, selectLists, fieldNames, selectNames, labelNames,
      inputTypes, readOnlyFM, invisibleFM, requiredFM,
      isModal, isWithRefs, selInpIds, listN4Page, listN4Modal,
      dateF, timeF, pageNo, totRow, lineCount, mCols, isLocale, lastProp;

  document.addEventListener("DOMContentLoaded", function(event) {

    jsObjData  = @(new HtmlString(Model.jsObjData ?? ""));
    dataList   = jsObjData.data;

    selectLists = @(new HtmlString(Model.selectLists ?? "''"));

    fieldNames  = @(new HtmlString(ArrayToString.getStringWithComma(Model.fieldNames)));
    selectNames = @(new HtmlString(ArrayToString.getStringWithComma(Model.selectFields)));
    labelNames  = @(new HtmlString(ArrayToString.getStringWithComma(Model.labelNames)));
    inputTypes  = @(new HtmlString(ArrayToString.getStringWithComma(Model.inputTypes)));
    readOnlyFM  = @(new HtmlString(ArrayToString.getStringWithComma(
                      Model.readOnlyFM.Select(x => x.ToString()).ToArray())));
    invisibleFM = @(new HtmlString(ArrayToString.getStringWithComma(
                      Model.invisibleFM.Select(x => x.ToString()).ToArray())));
    requiredFM  = @(new HtmlString(ArrayToString.getStringWithComma(
                      Model.requiredFM.Select(x => x.ToString()).ToArray())));
    isModal     = @(Model.isModal ? "true" : "false");
    isWithRefs  = @(Model.isWithRefs ? "true" : "false");
    isLocale    = @(Model.isLocale ? "true" : "false");
</script>

JavaScript — Tablo Veri Ayarları

JavaScript — Sayfa Değişkenleri
    excelCols = @(new HtmlString(Model.excelCols));
    lastProp  = "@Model.fieldNames[0]";
    pageNo    = 1;

    selInpIds = {
      yeniK:     [{ id:"y_2", name:"adr_path" }, { id:"y_3", name:"code_type" }],
      araK:      [{ id:"s_3", name:"adr_path" }, { id:"s_4", name:"code_type" }, { id:"s_5", name:"rec_user" }],
      guncelleK: [{ id:"g_3", name:"adr_path" }, { id:"g_4", name:"code_type" }]
    };

    listN4Page  = [{ id:"paths", name:"adr_path" }, { id:"types", name:"code_type" }, { id:"codes", name:"rec_user" }];
    listN4Modal = [{ id:"paths", name:"adr_path" }, { id:"types", name:"code_type" }];

    totRow    = @(Model.tableData != null ? Model.tableData.Length : 0);
    dateF     = "@Model.dateFormatter.getStringDF()";
    timeF     = "@Model.dateFormatter.getStringTF()";
    lineCount = @Model.sessionBean.getLineCount();
    mCols     = 2;

    setList(listN4Page, selectLists);
    setPage();
Razor — Bootstrap Modal
<div class="modal fade" id="guncM" role="dialog">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title">@Model.pageTitle Güncelle</h4>
                <button type="button" class="close" data-dismiss="modal">&times;</button>
            </div>
            <form id="guncelleK" class="form" enctype="multipart/form-data" method="post">
                <div class="modal-body">
                    <table class="table table-borderless">
                        <tbody id="modalTb"></tbody>
                    </table>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-outline-info btn-sm"
                            onclick='sendUpdate("@Model.pageName","guncelleK")'>Kaydet</button>
                    <button type="button" class="btn btn-outline-info btn-sm"
                            onclick='sendDownload("@Model.pageName","guncelleK","g_2",false)'>
                        Dosya İndir
                    </button>
                    <button type="button" class="btn btn-outline-danger btn-sm"
                            onclick='sendDelete("@Model.pageName","guncelleK")'>Sil</button>
                    <button type="button" class="btn btn-secondary btn-sm"
                            data-dismiss="modal">Kapat</button>
                </div>
            </form>
        </div>
    </div>
</div>

JavaScript — Sayfalandırma Fonksiyonları

csbca.js JavaScript dosyasındaki sayfalandırma fonksiyonları:

JavaScript — setPage / paging / getPage
// For setting html table line size and calling getPage function
function setPage() {
    if (window.dataList !== "") {
        window.lineCount = document.getElementById("p_size").value;
        getPage(window.pageNo);
    }
}

// For setting html table page value and calling getPage function
function paging(pageB) {
    let page = document.getElementById("page" + pageB).value;
    logStr("page: " + page);
    getPage(page);
}

// For setting html table page lines
function getPage(page) {
    let i = 0, j = 0, order = 0, elem, c;
    let k = 0, n = 0;
    let tableStr = "";

    if (page == "O") {
        if (window.pageNo > 1) page = window.pageNo - 1;
        else page = 1;

        if (document.getElementById("page1").value > 1) {
            for (i = 1; i <= 5; i++) {
                elem = document.getElementById("page" + i);
                c = elem.value - 1;
                elem.value = c;
                elem.innerHTML = c;
            }
        }
    } else if (page == "S") {
        if (window.pageNo <= ((window.totRow / window.lineCount) - 1) + 2)
            page = (window.pageNo - 1) + 2;

        if (document.getElementById("page5").value <= ((window.totRow / window.lineCount) - 1) + 2) {
            for (i = 1; i <= 5; i++) {
                elem = document.getElementById("page" + i);
                c = (elem.value - 1) + 2;
                elem.value = c;
                elem.innerHTML = c;
            }
        }
    }
    window.pageNo = page;

JavaScript — HTML Tablo Satırları

JavaScript — Satır Oluşturma
if (k > 0 && window.totRow > 0) {
    order = 1;
    for (i = n; i < k; i++) {
        for (j = 0; j < window.fieldNames.length; j++) {
            if (j == 0) {
                if (window.isModal)
                    tableStr += "<tr><td>" + order + "</td><td onclick=\"getModal("
                                + window.dataList[i][fieldNames[j]] + ")\"";
                else
                    tableStr += "<tr><td>" + order + "</td><td onclick=\"getUpdateForm("
                                + window.dataList[i][fieldNames[j]] + ")\"";
            } else {
                tableStr += "<td";
            }

            if (j == window.invisibleFM[j])
                tableStr += " style=\"display:none;\"";

            tableStr += ">" + window.dataList[i][window.fieldNames[j]] + "</td>";
        }
        tableStr += "</tr>";
        order++;
    }
    document.getElementById("listTb").innerHTML = tableStr;
}

JavaScript — Modal Form İnşası

JavaScript — Modal Alan Oluşturma
if ((j % mCols) == 0)
    tableStr += "<tr>";

tableStr += "<td><label for=\"g_" + (j+1) + "\">" + window.labelNames[j] + ":</label></td>"
          + "<td><input class=\"form-control form-control-sm\" id=\"g_" + (j+1) + "\"";

if (window.inputTypes[j] == "datetime-local")
    tableStr += " value=\"" + dateTimeFormat(window.dataList[i][window.fieldNames[j]], true)
              + "\" name=\"" + window.fieldNames[j] + "\"";
else if (window.inputTypes[j] == "date")
    tableStr += " value=\"" + dateTimeFormat(window.dataList[i][window.fieldNames[j]], false)
              + "\" name=\"" + window.fieldNames[j] + "\"";
else
    tableStr += " value=\"" + window.dataList[i][window.fieldNames[j]]
              + "\" name=\"" + window.fieldNames[j] + "\"";

if (j == window.readOnlyFM[j])  tableStr += " readonly";
if (j == window.requiredFM[j])  tableStr += " required";

tableStr += " type=\"" + window.inputTypes[j] + "\"";

isList = false;
if (window.listN4Modal) {
    for (h = 0; h < n; h++) {
        if (window.listN4Modal[h].name == window.fieldNames[j]) {
            tableStr += " list=\"" + window.listN4Modal[h].id + "\"></td>"
                      + "<datalist id=\"" + window.listN4Modal[h].id + "\"></datalist>";
            isList = true;
        }
    }
}
if (!isList) tableStr += "></td>";

JavaScript — Modal'a Alternatif Update Formu

JavaScript — getUpdateForm()
// For getting update form instead of modal
function getUpdateForm(id) {
    let k = window.fieldNames.length;
    let m = window.dataList ? window.dataList.length : 0;

    for (let i = 0; i < m; i++) {
        if (window.dataList[i][window.fieldNames[0]] == id) {
            for (let j = 0; j < k; j++) {
                if (window.inputTypes[j] == "datetime-local")
                    document.getElementById("g_" + (j+1)).value =
                        dateTimeFormat(window.dataList[i][window.fieldNames[j]], true);
                else if (window.inputTypes[j] == "date")
                    document.getElementById("g_" + (j+1)).value =
                        dateTimeFormat(window.dataList[i][window.fieldNames[j]], false);
                else
                    document.getElementById("g_" + (j+1)).value =
                        window.dataList[i][window.fieldNames[j]];
            }
        }
    }
}

JavaScript — Ajax Arama ve JSON Parse

JavaScript — sendSelect / selectResponse
// For sending selection form data with ajax
function sendSelect(url, formId) {
    let formElement = document.getElementById(formId);
    let formData    = new FormData(formElement);

    if (window.isWithRefs)
        setSelectData(formData, formId);

    formData.append("action",   "select");
    formData.append("isLocale", window.isLocale);

    logFD(formData);
    sendForm(url, selectResponse, formData);
}

// For setting selection response data
function selectResponse(xhr) {
    if (xhr.responseText) {
        logStr(xhr.responseText);

        window.jsObjData = JSON.parse(xhr.responseText);
        window.dataList  = window.jsObjData.data;
        window.pageNo    = 1;

        logJD(window.jsObjData);

        if (window.dataList)
            window.totRow = window.dataList.length;

        putMessages();
    }
}

JavaScript — Dosya İndirme

JavaScript — sendDownload()
// For sending download form data to url with ajax
function sendDownload(url, formId, fileId, isPage) {
    let formElement = document.getElementById(formId);
    let formData    = new FormData(formElement);
    var fileName    = document.getElementById(fileId).value;

    if (isPage === true) fileName += ".html";

    if (isWithRefs)
        setSelectData(formData, formId);

    formData.append("action",   "download");
    formData.append("isLocale", window.isLocale);

    logFD(formData);

    let xhr = window.XMLHttpRequest
        ? new XMLHttpRequest()
        : new ActiveXObject("Microsoft.XMLHTTP");

    xhr.open("POST", url, true);
    xhr.responseType = "blob";

    xhr.onload = function() {
        if (xhr.readyState == 4 && xhr.status == 200) {
            downloadResponse(fileName, xhr.response);
        }
    };
    xhr.send(formData);
}

JavaScript — Excel / JSON / CSV Dışa Aktarım

JavaScript — exportToExcel / exportToJson / exportToCSV
// For exporting to excel file
function exportToExcel(file = "") {
    file = file ? file + ".xlsx" : "excel_list.xlsx";

    var workbook  = new ExcelJS.Workbook();
    var worksheet = workbook.addWorksheet("excel_list");

    worksheet.columns = excelCols;
    worksheet.addRows(dataList);

    workbook.xlsx.writeBuffer().then(function(data) {
        var blob = new Blob([data], {
            type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        });
        saveAs(blob, file);
    });
}

// For exporting to json file
function exportToJson(file = "") {
    let jsonList = getJSList();
    file = file ? file + ".json" : "json_list.json";
    let data = "application/json;charset=utf-8," + jsonList;
    exportData(data, file);
}

// For exporting to csv text file
function exportToCSV(file = "") {
    let csvList = getList();
    file = file ? file + ".csv" : "csv_list.csv";
    let data = "text/csv;charset=utf-8," + encodeURIComponent(csvList);
    exportData(data, file);
}

C# — PageModel Başlatma ve Yetki Kontrolü

C# — PageModel.OnPost()
if (process == null) process = new AdminProcess();

HttpContext.Request.Headers["Content-Type"] = "charset=utf-8";

if (httpContextA == null)
    httpContextA = new HttpContextAccessor();

httpContextA.HttpContext = HttpContext; // For transferring HttpContext to process

initModel();                                // Model initialization
process.initProcess(httpContextA, p);       // Process initialization
process.isDebug = p.isDebug;

process.checkSession();                     // Session control
process.checkAuthorized();                  // User authorization control

procData = process.doPost();                // Call page process / send actions to API

C# — HttpContext Başlatma

C# — initProcess / initContext
public void initProcess(IHttpContextAccessor httpContextA, BaseParameters p)
{
    initContext(httpContextA);
    initParameters(p);
}

// For initializing HttpContext, Request, Response and Session
public void initContext(IHttpContextAccessor httpContextA)
{
    this.httpContextA = httpContextA;
    request  = httpContextA.HttpContext.Request;
    response = httpContextA.HttpContext.Response;
    session  = httpContextA.HttpContext.Session;
}

C# — Arama İşlemi ve JSON Yanıtı

C# — select Action
if (p.action.Equals("select"))
{
    formSize = p.selectFields.Length;
    p.formData = new string[formSize];
    p.dateFormatter.setIsForm(true);
    p.dateFormatter.setTimeFormat(BaseParameters.NO);

    for (int i = 0; i < formSize; i++)
        p.formData[i] = request.Form[p.selectFields[i]].ToString();

    dbQuery = p.execTableWR.tableAction(p.action, p.formData, p.prepQueryWR);

    if (dbQuery)
        p.tableData = (string[][])p.execTableWR.selectData(p.dataType);
    else
        p.tableData = null;

    if (p.tableData != null)
    {
        p.jsonConverter = new JsonConverter(p.fieldNames, p.tableData, p.execTableWR);
        jsonData = p.jsonConverter.convert2Json();
        tableData = p.tableData;
    }
    messages = p.execTableWR.getMessages();

    return jsonData;
}

C# — INSERT / UPDATE / DELETE ve JSON Yanıtı

C# — DML İşlemleri
formSize = p.fieldNames.Length;
p.formData = new string[formSize];
p.dateFormatter.setIsForm(true);

if (isInsert) { p.formData[0] = "0"; n = 1; }

for (int i = n; i < formSize - 2; i++)
    p.formData[i] = request.Form[p.fieldNames[i]].ToString();

p.formData[formSize - 2] = p.sessionBean.getCode();
p.formData[formSize - 1] = now.ToString(dateTF);

dbQuery = p.execTableWR.tableActionWR(p.action, p.formData, p.prepQueryWR);

if (dbQuery)
{
    if (!isInsert) p.logBean.setLog(p, formSize);

    p.tableData = new string[1][];

    if (isInsert)
    {
        int k = 0;
        p.unqFieldData = new string[p.unqFields.Length];

        for (int i = 0; i < formSize; i++)
            if (i == p.unqMatchs[i]) { p.unqFieldData[k] = p.formData[i]; k++; }

        p.tableData[0] = p.execTableWR.getNewRecord(
            p.unqFields, p.unqFieldData, p.unqFieldTypes, p.prepQueryWR);
        p.formData[0] = p.tableData[0][0];
        p.logBean.setLog(p, formSize);
    }
    else
    {
        p.tableData[0] = p.formData;
        if (p.tableData[0] != null && p.tableData[0][5] != null)
            p.tableData[0][5] = p.dateFormatter.changeDateFormat(p.tableData[0][5]);
    }
    tableData = p.tableData;
}
else
{
    p.tableData   = null;
    messageString = "p.tableData is null!";
    errorString   = p.execTableWR.getErrorString();
    Console.WriteLine(messageString + "\n" + errorString);
}

p.jsonConverter = new JsonConverter(p.fieldNames, p.tableData, p.execTableWR);
jsonData = p.jsonConverter.convert2Json();
return jsonData;

Uygulama Ekran Görüntüleri

📷 Uygulama menülerinden bir kesit
CSBCA Menü
📷 Yeni veri girişte HTML5 zorunlu alan kontrolü
HTML5 Zorunlu Alan
📷 Bilgi aramak için HTML5 tarih seçme özelliği
HTML5 Tarih Seçimi
📷 Code formunun İngilizce olarak toplu görünümü
Code Formu Liste
📷 Code formunun modal görüntüsü
Code Formu Modal

C# — Form Parametrelerinin Belirlenmesi

Hepsinden önce form için parametrelerin belirlenmesi gerekiyor.

C# — initParams()
public new void initParams()
{
    base.initParams();
    isDebug     = false;
    tableNames  = new string[] { "csbc_user", "vt_csbc_user" };
    fieldNames  = new string[] { "id","user_name","user_code","user_psw","user_group",
                                  "e_mail","rec_status","page_size","rec_user","rec_date" };
    inputTypes  = new string[] { "number","text","text","password","text",
                                  "email","text","number","text","datetime-local" };
    selectFields = new string[] { "id","user_name","user_group","e_mail","rec_user","rec_date1","rec_date2" };
    selectITs    = new string[] { "number","text","text","email","text","date","date" };
    setLabels();

    colWidths    = new int[] { 10, 30, 10, 10, 10, 30, 10, 10, 10, 15 };  // Excel column widths
    readOnlyFM   = new int[] { 0, -1, -1, -1, -1, -1, -1, -1, 8, 9 };    // Read-only field map
    invisibleFM  = new int[] { -1, -1, -1, 3, -1, -1, -1, -1, -1, -1 };  // Invisible field map
    requiredFM   = new int[] { -1, 1, 2, 3, 4, 5, -1, -1, -1, -1 };      // Required field map
    equalityInt  = new int[] { EQ, LK, EQ, LK, EQ, BGE, SME };
    unqFields    = new string[] { "user_code" };
    unqFieldTypes = new int[] { STRING };
    unqMatchs    = new int[] { -1, -1, 2, -1, -1, -1, -1, -1, -1, -1 };
    fieldTypes   = new int[] { INTEGER, STRING, STRING, STRING, STRING, STRING, STRING, INTEGER, STRING, DATE };
    selectFTs    = new int[] { INTEGER, STRING, STRING, STRING, STRING, DATE, DATE };
    dataType     = STRING;
    setExcelCols();
    orderBy      = "id";

    refTableNames  = new string[] { "csbc_group", "csbc_status", "csbc_user" };
    refFieldNames  = new string[] { "group_name", "status_name", "user_code" };
    refFieldMatchs = new int[] { -1, -1, -1, -1, 4, -1, 6, -1, 8, -1 };

    dateFormatter = new DateFormatter();
    dateFormatter.setTimeFormat(HM);

    prepQueryWR = new PrepQueryWithRef();
    prepQueryWR.convert2EQLs(equalityInt);

    execTableWR = new ExecTableWithRef(runDB, tableNames, fieldNames, fieldTypes, orderBy,
                        selectFields, selectFTs, dateFormatter,
                        refTableNames, refFieldNames, refFieldMatchs, messageBean);

    passwordBean   = new PasswordBean(runDB, tableNames[0], fieldNames[0], fieldNames[3]);
    managePassword = new ManagePassword(defPasw, passwordBean, defMask);
    manageSelList  = new ManageSelList(runDB, refTableNames, refFieldNames);

    execTableWR.isAfterCommit = false;
    execTableWR.isDebug       = isDebug;
    authorized  = new string[] { "Admin" };
    isModal     = true;   // Modal or inline update form
    isWithRefs  = true;   // With or without reference tables
}
💡 İyi bir analiz çalışması ve ilişkisel veritabanı tasarımından sonra güçlü bir mimari kullanımı, kurumsal yazılım projelerinizde size %30–40 zaman kazancı sağlayabilir.