feat: Enhance error logging for PDF preview failures and SQL timeouts
- Implemented a new method `ShapeTableNames` to gather entity and navigation table names, ensuring no blanks or duplicates are included. - Updated `FdsMfrClient` to handle cases where schema queries return no tables, logging appropriate warnings and preventing misleading errors. - Introduced `PdfPreviewAsync` in `IntranetController` to manage PDF preview rendering, capturing detailed logs for failures and notifying users with readable error messages. - Added comprehensive unit tests for error logging and table name shaping to ensure robustness and correctness. - Documented decision to persist user action failures to the `fds__admin_logdebug` table, enhancing support diagnostics.
This commit is contained in:
@@ -92,21 +92,41 @@ public class FdsMfrClient : IDisposable
|
||||
foreach (DataRow nprw in dset.Tables("navigation_properties").Rows)
|
||||
NavProperties[nprw.nz("name").ToLower()] = nprw.toStringDictionary();
|
||||
|
||||
var sqlList = new List<string> { NewDatatableSql(EntityTableName) };
|
||||
var tableNames = new List<string> { EntityTableName };
|
||||
foreach (DataRow ttrw in dset.Tables("tables").Rows)
|
||||
// When mfr__getSchema itself failed (deadlock victim / timeout) there is no table name
|
||||
// to build the TOP(0) shape queries from. Running them anyway produced a second, misleading
|
||||
// "FROM [dbo].[]" error per sync and hid the real cause; the caller sees IsValid=false.
|
||||
var shapeTables = ShapeTableNames(EntityTableName, dset.Tables("tables").Rows);
|
||||
if (shapeTables.Length == 0)
|
||||
{
|
||||
sqlList.Add(NewDatatableSql(ttrw.nz("tablename")));
|
||||
tableNames.Add(ttrw.nz("tablename"));
|
||||
logger?.LogWarning("DatabaseSchema for {Entity}: schema query returned no entity table (exception={Exception}); skipping table-shape load",
|
||||
ThisEntityName, dset.Exception);
|
||||
_tableSet = new DataSet();
|
||||
return;
|
||||
}
|
||||
|
||||
_tableSet = Task.Run(async () => await getSQLDataSet_async(
|
||||
string.Join(Environment.NewLine, sqlList),
|
||||
string.Join(Environment.NewLine, shapeTables.Select(NewDatatableSql)),
|
||||
FdsShared.FDSConnectionString(),
|
||||
tablenames: tableNames.ToArray(),
|
||||
tablenames: shapeTables,
|
||||
options: new FdsSqlOptions(logger: logger))).Result.DataSet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entity table plus its navigation tables, without blanks: the list of tables whose
|
||||
/// (empty) shape is loaded. Empty when the entity table itself is unknown.
|
||||
/// </summary>
|
||||
internal static string[] ShapeTableNames(string entityTableName, DataRowCollection navTables)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(entityTableName)) return Array.Empty<string>();
|
||||
var names = new List<string> { entityTableName };
|
||||
foreach (DataRow row in navTables)
|
||||
{
|
||||
string tbl = row.nz("tablename");
|
||||
if (!string.IsNullOrWhiteSpace(tbl) && !names.Contains(tbl)) names.Add(tbl);
|
||||
}
|
||||
return names.ToArray();
|
||||
}
|
||||
|
||||
public DataSet TgtDataset(string setId)
|
||||
{
|
||||
var dset = new DataSet();
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
<member name="F:fds.FdsMfr.InvoiceFileDownloadConcurrency">
|
||||
<summary>Max parallel invoice-file downloads (independent per file).</summary>
|
||||
</member>
|
||||
<member name="M:fds.FdsMfrClient.DatabaseSchema.ShapeTableNames(System.String,System.Data.DataRowCollection)">
|
||||
<summary>
|
||||
Entity table plus its navigation tables, without blanks: the list of tables whose
|
||||
(empty) shape is loaded. Empty when the entity table itself is unknown.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:fds.FdsConfig">
|
||||
<summary>
|
||||
Holds the application <see cref="T:Microsoft.Extensions.Configuration.IConfiguration"/> supplied by the host (the Fuchs web app).
|
||||
|
||||
Reference in New Issue
Block a user