将当前的 Test 方法中的硬编码配置(如 connectionString, joins, config)改为通过读取 JSON 配置文件的方式来生成 material_config.json,并允许程序根据指定的 JSON 文件名称动态生成配置。这样可以进一步减少硬编码,提高灵活性和可维护性。以下,我将基于你的要求修改代码,保持现有功能(如动态枚举、AdditionalColumns 配置、IsShow 默认 true 等),并实现从 JSON 文件加载配置。
需求分析
1. 当前情况
-
硬编码:
-
connectionString:数据库连接字符串。
-
joins:JoinConfig 列表,定义表连接。
-
config:GeneratorConfig 对象,包含 Id, Name, EnumArray, Fields, MainTable, RequiredFields, HiddenFields, Tabs, EnumFields, AdditionalColumns。
-
-
生成逻辑:
-
使用 JsonConfigGenerator 生成 JSON 配置,写入 material_config.json。
-
-
现有功能:
-
DataColumnConfig 和 AdditionalColumnConfig 的 IsShow 默认为 true,隐藏时为 false。
-
配置驱动的 Tabs, Fields, EnumArray, 主表,动态枚举(tb_enum_info 的 load_sql)。
-
修复:多余逗号、Unicode、迭代器、Sequence contains no matching element。
-
2. 目标
-
通过 JSON 文件加载配置:
-
将 connectionString, joins, config 写入 JSON 文件(例如 material_input.json)。
-
程序根据指定的 JSON 文件名称(例如 material_input.json)读取配置。
-
-
动态生成:
-
根据 JSON 文件生成对应的输出文件(例如 material_config.json)。
-
支持多个配置文件,程序通过文件名称参数决定加载哪个配置。
-
-
保持功能:
-
现有逻辑:GenerateDataColumns, GetSelectFields, 枚举处理等。
-
IsShow 默认为 true,仅在 HiddenFields, DefaultHidden, 或 IsShow: false 时为 false。
-
-
简化硬编码:
-
移除 Test 方法中的硬编码配置。
-
3. 解决方案
-
JSON 配置文件:
-
定义 InputConfig 类,包含 ConnectionString, Joins, 和 GeneratorConfig。
-
示例 material_input.json:
json
{ "ConnectionString": "Server=.;Database=TestGenerate;User Id=sa;Password=MES!qazwsx;TrustServerCertificate=true", "Joins": [ { "MainTable": "tb_material", "MainAlias": "a", "JoinTable": "tb_material_group", "JoinAlias": "b", "OnClause": "a.group_id = b.id" }, // ... ], "GeneratorConfig": { "Id": "material", "Name": "物料管理", "EnumArray": ["1", "5", "6", "8", "9", "12", "16"], "Fields": [ { "Table": "a", "Field": "number", "Header": "物料编码", "FieldType": 0, "DataType": 0 }, // ... ], "MainTable": "tb_material", "MainAlias": "a", "RequiredFields": ["number", "name", "model", "group_id", "unit_id"], "HiddenFields": ["name"], "Tabs": [ { "DisplayName": "基本信息", "GroupKey": ["number", "model", "name", "disabledId", "unitId", "shelfLife", "enableShelfLife", "shelfLifeUnit", "groupId"] }, // ... ], "EnumFields": { "disabled_id": 1, "shelf_life_unit": 5, // ... }, "AdditionalColumns": [ { "TableName": "tb_material_group", "TableAlias": "b", "FieldName": "group_name", "Alias": "groupName" }, { "TableName": "tb_unit", "TableAlias": "c", "FieldName": "name", "Alias": "unitName", "IsShow": false }, // ... ] } }
-
-
修改程序:
-
新增 Test 方法,接受 JSON 文件路径参数。
-
读取 JSON 文件,反序列化为 InputConfig。
-
使用 JsonConfigGenerator 生成输出 JSON。
-
-
输出文件:
-
根据输入文件名生成输出文件名(例如,material_input.json 生成 material_config.json)。
-
-
保持现有代码:
-
JsonConfigGenerator 和相关记录类型(DataColumnConfig, AdditionalColumnConfig 等)不变。
-
优化后的代码
以下是修改后的代码,包含从 JSON 文件加载配置的逻辑。JsonConfigGenerator 和相关记录类型保持不变,仅更新 Test 方法和添加 InputConfig 类。
csharp
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
// 配置记录类型(保持不变)
public record JoinConfig(string MainTable, string MainAlias, string JoinTable, string JoinAlias, string OnClause);
public record TableField
{
public string Name { get; init; }
public string SqlType { get; init; }
public string Description { get; init; }
public bool IsEnum { get; init; }
public int FieldType { get; init; }
public int DataType { get; init; }
public Dictionary<string, string>? EnumValues { get; set; }
}
public record TableConfig(string Name, string Alias, List<TableField> Fields);
public record JsonConfig(
string Id,
string Name,
string Sql,
string SqlStatistics,
string Orderby,
List<string> EnumArray,
List<FieldConfig> Fields,
List<FieldConfig> AdvancedFilterFields,
List<DataColumnConfig> DataColumns,
List<TabConfig> Tabs);
public record FieldConfig(string Table, string Field, string Header, int FieldType, int DataType);
public record DataColumnConfig(
string Table,
string Field,
string Header,
int FieldType,
int DataType,
bool Require,
bool DefaultHidden,
bool Disabled,
bool IsShow = true,
Dictionary<string, object> ExtraInfo = null) : FieldConfig(Table, Field, Header, FieldType, DataType)
{
public DataColumnConfig(
string Table,
string Field,
string Header,
int FieldType,
int DataType,
bool Require,
bool DefaultHidden,
bool Disabled,
bool? IsShow,
Dictionary<string, object> ExtraInfo)
: this(Table, Field, Header, FieldType, DataType, Require, DefaultHidden, Disabled, IsShow ?? true, ExtraInfo ?? new())
{
}
}
public record TabConfig(string DisplayName, List<string> GroupKey);
public record AdditionalColumnConfig(
string TableName,
string TableAlias,
string FieldName,
string Alias,
bool Require = true,
bool DefaultHidden = false,
bool Disabled = false,
bool IsShow = true
);
// 配置类
public class GeneratorConfig
{
public string Id { get; init; } = "material";
public string Name { get; init; } = "物料管理";
public List<string> EnumArray { get; init; } = [];
public List<FieldConfig> Fields { get; init; } = [];
public string MainTable { get; init; } = "";
public string MainAlias { get; init; } = "";
public HashSet<string> RequiredFields { get; init; } = [];
public HashSet<string> HiddenFields { get; init; } = [];
public List<TabConfig> Tabs { get; init; } = [];
public Dictionary<string, int> EnumFields { get; init; } = new();
public List<AdditionalColumnConfig> AdditionalColumns { get; init; } = [];
}
// 输入配置类(新增)
public class InputConfig
{
public string ConnectionString { get; init; } = "";
public List<JoinConfig> Joins { get; init; } = [];
public GeneratorConfig GeneratorConfig { get; init; } = new();
}
// JsonConfigGenerator(保持不变)
public class JsonConfigGenerator
{
private readonly string _connectionString;
private readonly List<JoinConfig> _joins;
private readonly GeneratorConfig _config;
private List<TableConfig> _tables = [];
private Dictionary<int, Dictionary<string, string>> _enumValuesCache = new();
public JsonConfigGenerator(string connectionString, List<JoinConfig> joins, GeneratorConfig config = null)
{
_connectionString = connectionString;
_joins = joins;
_config = config ?? new GeneratorConfig();
}
public async Task<string> GenerateAsync()
{
_tables = await LoadTablesAsync();
await LoadEnumValuesAsync();
var config = new JsonConfig(
Id: _config.Id,
Name: _config.Name,
Sql: GenerateSql(),
SqlStatistics: GenerateSqlStatistics(),
Orderby: "a.last_modify_date DESC",
EnumArray: _config.EnumArray,
Fields: _config.Fields,
AdvancedFilterFields: GenerateAdvancedFilterFields(),
DataColumns: GenerateDataColumns(),
Tabs: _config.Tabs
);
var options = new JsonSerializerOptions
{
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
return JsonSerializer.Serialize(config, options);
}
private async Task<List<TableConfig>> LoadTablesAsync()
{
var tables = new List<TableConfig>();
var tableNames = _joins.Select(j => j.MainTable).Concat(_joins.Select(j => j.JoinTable)).Distinct();
using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync();
foreach (var tableName in tableNames)
{
var (schema, name) = tableName.Contains(".") ? (tableName.Split('.')[0], tableName.Split('.').Last()) : ("dbo", tableName);
var alias = _joins.FirstOrDefault(j => j.JoinTable == tableName)?.JoinAlias ?? _joins.FirstOrDefault(j => j.MainTable == tableName)?.MainAlias ?? "a";
var fields = new List<TableField>();
var query = @"
SELECT
c.COLUMN_NAME AS Name,
c.DATA_TYPE + CASE
WHEN c.DATA_TYPE IN ('nvarchar', 'varchar', 'char', 'nchar')
THEN '(' + ISNULL(CAST(c.CHARACTER_MAXIMUM_LENGTH AS NVARCHAR), 'MAX') + ')'
ELSE '' END AS SqlType,
ISNULL(CAST(p.value AS NVARCHAR), c.COLUMN_NAME) AS Description
FROM INFORMATION_SCHEMA.COLUMNS c
LEFT JOIN sys.extended_properties p ON p.major_id = OBJECT_ID(@schema + '.' + @name)
AND p.minor_id = COLUMNPROPERTY(OBJECT_ID(@schema + '.' + @name), c.COLUMN_NAME, 'ColumnId')
AND p.name = 'MS_Description'
WHERE c.TABLE_SCHEMA = @schema AND c.TABLE_NAME = @name";
using var command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("@schema", schema);
command.Parameters.AddWithValue("@name", name);
using var reader = await command.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
var fieldName = reader.GetString(0);
var sqlType = reader.GetString(1);
var description = reader.GetString(2);
var isEnum = sqlType.StartsWith("tinyint", StringComparison.OrdinalIgnoreCase) || fieldName.EndsWith("_id", StringComparison.OrdinalIgnoreCase);
var fieldType = isEnum ? 3 : sqlType.StartsWith("datetime", StringComparison.OrdinalIgnoreCase) ? 2 : 0;
var dataType = _config.EnumFields.TryGetValue(fieldName, out var enumId) ? enumId : (isEnum ? 0 : 0);
var enumValues = isEnum && _config.EnumFields.ContainsKey(fieldName) && _enumValuesCache.TryGetValue(dataType, out var values)
? values
: null;
var field = new TableField
{
Name = fieldName,
SqlType = sqlType,
Description = description,
IsEnum = isEnum,
FieldType = fieldType,
DataType = dataType,
EnumValues = enumValues
};
fields.Add(field);
}
if (fields.Any())
tables.Add(new(tableName, alias, fields));
}
return tables;
}
private async Task LoadEnumValuesAsync()
{
using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync();
foreach (var (fieldName, enumId) in _config.EnumFields)
{
var query = "SELECT load_sql FROM tb_enum_info WHERE id = @id";
using var command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("@id", enumId);
var loadSql = await command.ExecuteScalarAsync() as string;
if (string.IsNullOrEmpty(loadSql))
{
Console.WriteLine($"Warning: No load_sql found for enumId {enumId} ({fieldName}).");
_enumValuesCache[enumId] = new() { ["0"] = "未知" };
continue;
}
try
{
using var enumCommand = new SqlCommand(loadSql, connection);
using var reader = await enumCommand.ExecuteReaderAsync();
var values = new Dictionary<string, string>();
while (await reader.ReadAsync())
{
var id = reader.GetValue(0)?.ToString();
var name = reader.GetString(1);
if (id != null)
values[id] = name;
}
_enumValuesCache[enumId] = values.Any() ? values : new() { ["0"] = "未知" };
}
catch (Exception ex)
{
Console.WriteLine($"Error executing load_sql for enumId {enumId} ({fieldName}): {ex.Message}");
_enumValuesCache[enumId] = new() { ["0"] = "未知" };
}
}
}
private string GetFieldDescription(string tableName, string fieldName)
{
var table = _tables.FirstOrDefault(t => t.Name == tableName);
if (table == null)
{
Console.WriteLine($"Warning: Table '{tableName}' not found.");
return fieldName;
}
var field = table.Fields.FirstOrDefault(f => f.Name == fieldName);
if (field == null)
{
Console.WriteLine($"Warning: Field '{fieldName}' not found in table '{tableName}'.");
return fieldName;
}
return field.Description;
}
private string GenerateSql() =>
$"SELECT {string.Join(", ", GetSelectFields())} FROM {_config.MainTable} {_config.MainAlias} {string.Join(" ", _joins.Select(j => $"LEFT JOIN {j.JoinTable} {j.JoinAlias} ON {j.OnClause}"))} WHERE 1=1 {{@condition}}";
private IEnumerable<string> GetSelectFields()
{
var main = _tables.FirstOrDefault(t => t.Name == _config.MainTable);
if (main == null)
{
Console.WriteLine($"Warning: Table '{_config.MainTable}' not found.");
yield break;
}
foreach (var f in main.Fields)
{
var alias = f.Name is "create_date" ? "createDate" : f.Name is "last_modify_date" ? "lastModifyDate" : f.Name;
if (f.IsEnum)
{
yield return $"CAST(a.{f.Name} AS NVARCHAR(100)) AS {f.Name}";
if (f.EnumValues != null && f.EnumValues.Any() && _config.EnumFields.ContainsKey(f.Name))
{
var caseWhen = $"CASE {string.Join(" ", f.EnumValues.Select(kv => $"WHEN a.{f.Name} = {kv.Key} THEN N'{kv.Value}'"))} END AS {f.Name}Name";
yield return caseWhen;
}
}
else
{
yield return $"a.{f.Name} AS {alias}";
}
}
foreach (var col in _config.AdditionalColumns)
{
yield return $"{col.TableAlias}.{col.FieldName} AS {col.Alias}";
}
}
private string GenerateSqlStatistics() =>
$"SELECT COUNT(0) AS total FROM {_config.MainTable} {_config.MainAlias} {string.Join(" ", _joins.Select(j => $"LEFT JOIN {j.JoinTable} {j.JoinAlias} ON {j.OnClause}"))} WHERE 1=1 {{@condition}}";
private List<FieldConfig> GenerateAdvancedFilterFields()
{
var main = _tables.FirstOrDefault(t => t.Name == _config.MainTable);
return main?.Fields.Select(f => new FieldConfig("a", f.Name, f.Description, f.FieldType, f.DataType)).ToList() ?? [];
}
private List<DataColumnConfig> GenerateDataColumns()
{
var columns = new List<DataColumnConfig>();
var main = _tables.FirstOrDefault(t => t.Name == _config.MainTable);
if (main == null) return columns;
foreach (var f in main.Fields)
{
var alias = f.Name is "create_date" ? "createDate" : f.Name is "last_modify_date" ? "lastModifyDate" : f.Name;
var isRequired = _config.RequiredFields.Contains(f.Name);
var isHidden = _config.HiddenFields.Contains(f.Name);
columns.Add(new("a", alias, f.Description, f.FieldType, f.DataType, isRequired, isHidden, isHidden, !isHidden && !f.IsEnum, new()));
if (f.IsEnum && f.EnumValues != null && _config.EnumFields.ContainsKey(f.Name))
{
columns.Add(new("a", $"{f.Name}Name", f.Description, 0, 0, isRequired, false, false, true, new()));
}
}
columns.AddRange(_config.AdditionalColumns.Select(col =>
new DataColumnConfig(
col.TableAlias,
col.Alias,
GetFieldDescription(col.TableName, col.FieldName) ?? col.FieldName,
0,
0,
col.Require,
col.DefaultHidden,
col.Disabled,
col.IsShow && !col.DefaultHidden,
new()
)));
return columns;
}
}
// 测试方法
public class Program
{
public static async Task Test(string inputJsonFile)
{
try
{
// 读取 JSON 配置文件
if (!File.Exists(inputJsonFile))
{
Console.WriteLine($"Error: Input JSON file '{inputJsonFile}' not found.");
return;
}
var jsonContent = await File.ReadAllTextAsync(inputJsonFile);
var inputConfig = JsonSerializer.Deserialize<InputConfig>(jsonContent, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true // 支持大小写不敏感
});
if (inputConfig == null)
{
Console.WriteLine("Error: Failed to deserialize input JSON.");
return;
}
// 创建 JsonConfigGenerator
var generator = new JsonConfigGenerator(
inputConfig.ConnectionString,
inputConfig.Joins,
inputConfig.GeneratorConfig
);
// 生成 JSON 配置
var json = await generator.GenerateAsync();
// 生成输出文件名(基于输入文件名)
var outputFileName = Path.GetFileNameWithoutExtension(inputJsonFile).Replace("_input", "") + "_config.json";
await File.WriteAllTextAsync(outputFileName, json);
Console.WriteLine($"JSON config generated: {outputFileName}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
public static async Task Main()
{
// 示例:传入 JSON 文件路径
await Test("material_input.json");
}
}
关键修改
1. InputConfig 类
-
定义:
csharp
public class InputConfig { public string ConnectionString { get; init; } = ""; public List<JoinConfig> Joins { get; init; } = []; public GeneratorConfig GeneratorConfig { get; init; } = new(); }
-
作用:
-
封装 ConnectionString, Joins, 和 GeneratorConfig,对应原 Test 方法中的硬编码。
-
2. Test 方法
-
修改:
-
接受 inputJsonFile 参数:
csharp
public static async Task Test(string inputJsonFile)
-
读取 JSON 文件:
csharp
var jsonContent = await File.ReadAllTextAsync(inputJsonFile); var inputConfig = JsonSerializer.Deserialize<InputConfig>(jsonContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
-
动态生成输出文件名:
csharp
var outputFileName = Path.GetFileNameWithoutExtension(inputJsonFile).Replace("_input", "") + "_config.json";
-
-
错误处理:
-
检查文件存在性:
csharp
if (!File.Exists(inputJsonFile)) { Console.WriteLine($"Error: Input JSON file '{inputJsonFile}' not found."); return; }
-
处理反序列化失败:
csharp
if (inputConfig == null) { Console.WriteLine("Error: Failed to deserialize input JSON."); return; }
-
3. JSON 配置文件
-
示例 material_input.json:
json
{ "ConnectionString": "Server=.;Database=TestGenerate;User Id=sa;Password=MES!qazwsx;TrustServerCertificate=true", "Joins": [ { "MainTable": "tb_material", "MainAlias": "a", "JoinTable": "tb_material_group", "JoinAlias": "b", "OnClause": "a.group_id = b.id" }, { "MainTable": "tb_material", "MainAlias": "a", "JoinTable": "tb_unit", "JoinAlias": "c", "OnClause": "a.unit_id = c.id" }, { "MainTable": "tb_material", "MainAlias": "a", "JoinTable": "tb_factory", "JoinAlias": "d", "OnClause": "d.id = a.factory_id" }, { "MainTable": "tb_material", "MainAlias": "a", "JoinTable": "WMSIdentityServer.dbo.AbpUsers", "JoinAlias": "e", "OnClause": "e.fid = a.creator_id" }, { "MainTable": "tb_material", "MainAlias": "a", "JoinTable": "WMSIdentityServer.dbo.AbpUsers", "JoinAlias": "f", "OnClause": "f.fid = a.last_modifier_id" } ], "GeneratorConfig": { "Id": "material", "Name": "物料管理", "EnumArray": ["1", "5", "6", "8", "9", "12", "16"], "Fields": [ { "Table": "a", "Field": "number", "Header": "物料编码", "FieldType": 0, "DataType": 0 }, { "Table": "a", "Field": "name", "Header": "物料名称", "FieldType": 0, "DataType": 0 }, { "Table": "a", "Field": "model", "Header": "规格型号", "FieldType": 0, "DataType": 0 } ], "MainTable": "tb_material", "MainAlias": "a", "RequiredFields": ["number", "name", "model", "group_id", "unit_id"], "HiddenFields": ["name"], "Tabs": [ { "DisplayName": "基本信息", "GroupKey": ["number", "model", "name", "disabledId", "unitId", "shelfLife", "enableShelfLife", "shelfLifeUnit", "groupId"] }, { "DisplayName": "其它", "GroupKey": ["creator", "createDate", "last_modifier", "lastModifyDate"] } ], "EnumFields": { "disabled_id": 1, "shelf_life_unit": 5, "enable_shelf_life": 6, "unit_id": 8, "group_id": 9, "factory_id": 12, "creator_id": 16, "last_modifier_id": 16 }, "AdditionalColumns": [ { "TableName": "tb_material_group", "TableAlias": "b", "FieldName": "group_name", "Alias": "groupName" }, { "TableName": "tb_unit", "TableAlias": "c", "FieldName": "name", "Alias": "unitName", "IsShow": false }, { "TableName": "WMSIdentityServer.dbo.AbpUsers", "TableAlias": "e", "FieldName": "UserName", "Alias": "creator" }, { "TableName": "WMSIdentityServer.dbo.AbpUsers", "TableAlias": "f", "FieldName": "UserName", "Alias": "last_modifier" } ] } }
4. 未修改部分
-
JsonConfigGenerator:
-
保持原有逻辑,包括 GenerateDataColumns, GetSelectFields, 枚举处理等。
-
IsShow 逻辑:
-
主表字段:!isHidden && !f.IsEnum(非隐藏非枚举为 true)。
-
枚举名称字段:true。
-
附加列:col.IsShow && !col.DefaultHidden。
-
-
-
其他功能:
-
动态枚举:tb_enum_info 的 load_sql。
-
修复:多余逗号、Unicode、迭代器、Sequence contains no matching element。
-
使用方法
-
创建 JSON 配置文件:
-
创建 material_input.json,内容如上。
-
放置在项目目录或指定路径。
-
-
安装 NuGet 包:
bash
dotnet add package System.Data.SqlClient --version 4.8.5 dotnet add package System.Text.Json --version 8.0.0
-
配置数据库:
-
确保连接字符串有效:
json
"ConnectionString": "Server=.;Database=TestGenerate;User Id=sa;Password=MES!qazwsx;TrustServerCertificate=true"
-
tb_enum_info 和枚举表:
sql
CREATE TABLE tb_enum_info ( id INT PRIMARY KEY, name NVARCHAR(100), load_sql NVARCHAR(MAX) ); INSERT INTO tb_enum_info (id, name, load_sql) VALUES (1, 'disabled_id', 'SELECT id, name FROM tb_disabled_status'), (5, 'shelf_life_unit', 'SELECT id, name FROM tb_shelf_life_units'), (6, 'enable_shelf_life', 'SELECT id, name FROM tb_enable_shelf_life'), (8, 'unit_id', 'SELECT id, name FROM tb_units'), (9, 'group_id', 'SELECT id, name FROM tb_material_groups'), (12, 'factory_id', 'SELECT id, name FROM tb_factories'), (16, 'creator_id', 'SELECT fid, UserName FROM WMSIdentityServer.dbo.AbpUsers'); CREATE TABLE tb_shelf_life_units ( id INT PRIMARY KEY, name NVARCHAR(50) ); INSERT INTO tb_shelf_life_units (id, name) VALUES (1, '无'), (2, '日'), (3, '月'), (4, '年');
-
MS_Description:
sql
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'物料编码', @level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'tb_material', @level2type=N'COLUMN', @level2name=N'number';
-
-
运行:
-
执行程序,指定 JSON 文件:
bash
dotnet run
-
或在代码中调用:
csharp
await Program.Test("material_input.json");
-
-
验证输出:
-
检查生成的 material_config.json:
-
DataColumns 中 IsShow 默认为 true,例如:
json
{ "Table": "a", "Field": "number", "Header": "物料编码", "FieldType": 0, "DataType": 0, "Require": true, "DefaultHidden": false, "Disabled": false, "IsShow": true, "ExtraInfo": {} }, { "Table": "a", "Field": "name", "Header": "物料名称", "FieldType": 0, "DataType": 0, "Require": true, "DefaultHidden": true, "Disabled": true, "IsShow": false, "ExtraInfo": {} }, { "Table": "b", "Field": "groupName", "Header": "分组名称", "FieldType": 0, "DataType": 0, "Require": true, "DefaultHidden": false, "Disabled": false, "IsShow": true, "ExtraInfo": {} }, { "Table": "c", "Field": "unitName", "Header": "单位名称", "FieldType": 0, "DataType": 0, "Require": true, "DefaultHidden": false, "Disabled": false, "IsShow": false, "ExtraInfo": {} }
-
Sql 包含附加列:
sql
b.group_name AS groupName, c.name AS unitName, e.UserName AS creator, f.UserName AS last_modifier
-
-
-
支持多配置文件:
-
创建其他配置文件(如 product_input.json),调整 Id, MainTable 等。
-
调用:
csharp
await Program.Test("product_input.json"); // 生成 product_config.json
-
-
ABP 集成:
-
使用生成的 JSON:
csharp
public async Task<PagedResultDto<MaterialDto>> GetPagedAsync(MaterialQueryInput input) { var config = JsonSerializer.Deserialize<JsonConfig>(File.ReadAllText("material_config.json")); using var connection = new SqlConnection("..."); var query = config.Sql.Replace("{@condition}", BuildCondition(input)); return await query.ToPagedResultAsync(input); }
-
注意事项
-
JSON 文件格式:
-
确保 material_input.json 格式正确,字段名匹配 InputConfig 属性。
-
使用 PropertyNameCaseInsensitive = true 支持大小写不敏感。
-
-
文件路径:
-
默认在项目目录查找 material_input.json。
-
可指定绝对路径:
csharp
await Program.Test("C:/Configs/material_input.json");
-
-
输出文件名:
-
自动从输入文件名生成(如 material_input.json -> material_config.json)。
-
可自定义逻辑,例如:
csharp
var outputFileName = _config.Id + "_config.json"; // 使用 Id 生成
-
-
数据库:
-
验证连接字符串和表结构:
sql
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME IN ('tb_material', 'tb_material_group', 'tb_unit', 'tb_factory', 'tb_enum_info'); SELECT * FROM tb_enum_info;
-
-
调试:
-
检查警告:
Warning: Table 'tb_material' not found. Warning,No load_sql found for enumId 5.
-
确保 tb_enum_info 包含 id 1, 5, 6, 8, 9, 12, 16。
-
-
扩展:
-
支持批量处理多个 JSON 文件:
csharp
var files = Directory.GetFiles("Configs", "*_input.json"); foreach (var file in files) { await Program.Test(file); }
-
总结
-
修改:
-
新增 InputConfig 类,封装 ConnectionString, Joins, GeneratorConfig。
-
Test 方法从 JSON 文件(如 material_input.json)读取配置,生成 material_config.json。
-
移除硬编码,程序根据输入文件路径动态生成。
-
-
保留功能:
-
IsShow 默认为 true,仅在 HiddenFields, DefaultHidden, 或 IsShow: false 时为 false。
-
配置驱动:Tabs, Fields, EnumArray, 主表,AdditionalColumns。
-
动态枚举:tb_enum_info 的 load_sql。
-
修复:多余逗号、Unicode、迭代器、Sequence contains no matching element。
-
-
JSON 输出:
-
与原 Test 方法一致,DataColumns 和 Sql 包含配置的字段。
-
下一步:
-
提供其他 JSON 配置文件(如 product_input.json)进行测试。
-
指定是否需要自定义输出文件名逻辑。
-
确认数据库表结构和 tb_enum_info 数据。
请提供细节(如其他配置文件或要求),我可以进一步优化!