将DataTable 转成 List<dynamic>,主要用于给dapper批量操作时传参数。

本文介绍了一个简化Dapper操作的老项目中批量处理DataTable的静态方法,通过筛选列并转换为动态对象列表,以减少匿名对象创建。适合维护项目中的数据操作。

在维护一个老项目过程中,为了愉快的使用 dapper 从datatable中获取要批量操作的数据而不用再手动写一堆匿名对象集合,所以写了个下面的静态方法,用来支持dapper的写数据库方法。记录一下以免以后做重复工作。直接上代码:

/// <summary>
/// 将DataTable 转成 List<dynamic>,主要用于给dapper批量操作时传参数。
/// </summary>
/// <param name="table">要转换的DataTable对象</param>
/// <param name="filterFields">要筛选的列。默认不传,此时返回全部列</param>
/// <param name="includeOrExclude">指定上一个参数条件是要保留的列还是要排除的列</param>
/// <returns></returns>
public static List<dynamic> ToDynamicList(this DataTable table, string[] filterFields = null, bool includeOrExclude = true)
{
    var modelList = new List<dynamic>();
    var isFilter = filterFields != null && filterFields.Any();
    IEnumerable reservedColumns = table.Columns;
    if (isFilter)
        reservedColumns = table.Columns.Cast<DataColumn>().Where(c => filterFields.Contains(c.ColumnName) == includeOrExclude);
    foreach (DataRow row in table.Rows)
    {
        dynamic model = new ExpandoObject();
        var dict = (IDictionary<string, object>)model;
        foreach (DataColumn column in reservedColumns)
        {
            dict[column.ColumnName] = row[column];
        }
        modelList.Add(model);
    }
    return modelList;
}

然后,在操作Dapper 批量的增、删除、改 数据库表中的数据时,就可以这样从dataTable获取数据:

bool commitOK = false;
using (IDbConnection con = new System.Data.SqlClient.SqlConnection(constr))
{
    if (con.State == ConnectionState.Closed)
        con.Open();
    IDbTransaction transaction = con.BeginTransaction();

    var strInsert = $"insert into PriceStrategy(item_clsno, model, color, jhPrice, pfPrice) values(@item_clsno, @model, @color, @jhPrice, @pfPrice)";
    var strUpdate = $"update PriceStrategyset model=@model, color=@color, jhPrice=@jhPrice, pfPrice=@pfPrice,updatedTime=getdate() where id=@id";
    var strDelete = $"delete PriceStrategywhere id=@id";

    if (dataTable.GetChanges(DataRowState.Added)?.Rows?.Count > 0)
        await con.ExecuteAsync(strInsert, dataTable.GetChanges(DataRowState.Added).ToDynamicList(new [] { "item_clsno", "model", "color", "jhPrice", "pfPrice" }), transaction);
    if (dataTable.GetChanges(DataRowState.Modified)?.Rows?.Count > 0)
        await con.ExecuteAsync(strUpdate, dataTable.GetChanges(DataRowState.Modified).ToDynamicList(new [] { "id", "model", "color", "jhPrice", "pfPrice" }), transaction);
    if (dataTable.GetChanges(DataRowState.Deleted)?.Rows?.Count > 0)
        await con.ExecuteAsync(strDelete, dataTable.GetChanges(DataRowState.Deleted).ToDynamicList(new [] { "id" }), transaction);
    try
    {
        transaction.Commit();
        commitOK = true;
    }
    catch
    {
        transaction.Rollback();
        throw;
    }
}
if (commitOK)
{
    MessageBox.Show(this, "保存成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

上面代码中的三个调用都使用了静态方法的列筛选,如果你的项目是小数据量、不太多的列则上面的方法在不考虑性能的情况下完全可以粗暴的改为直接.ToDynamicList() 即把整个datatable的所有列都转成List<dynamic>集合,完全没有问题。

这样操作比 Ado.Net 时代确实跨进了一步。当然现代开发都流行使用 EntityFrameworkCore 等功能更强大的ORM工具。如果你像我一样是在维护一些老项目,希望本篇博文对你有帮助,别忘记点个赞。

using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Dynamic; using System.IO; using System.Linq; using System.Threading.Tasks; using AutoMapper; using MES.Application.InpuStorage.WInterface; using MES.Domain.Entities; using MES.Domain.InpuStorage.WInterface; using MES.Shared.DTOs.Requests.InpuStorage; using MES.Shared.DTOs.Responses.InputStorage; using MES.Shared.Utilities; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using SqlSugar; using static MES.Shared.Utilities.materialConfigsControl; // 主服务类(实现接口) namespace MES.Application.InpuStorage.Repository { public class InputStorageService : IInputStorageService { private readonly IMapper _mapper; private readonly IPrintDataMapperFactory _mapperFactory; private readonly IInputStorageControl _inputStorageControl; private readonly ILogger _logger; private readonly Dictionary<string, MaterialConfig> _materialConfigs; private readonly string _baseReportPath; // 常量定义 private const string StatusNG = "NG"; private const string StatusOK = "OK"; /// <summary> /// 列印標籤要加的卡點 /// </summary> private List<string> CheckProcedures { get; } = new List<string> { "PDL_CheckPackListPVS", "PDL_CheckPackListFCC", "PDL_CheckPackListQnty", "PDL_CheckPackListProdBasic", "PDL_CheckPackListOSP", "PDL_CheckPackOSP_2433", "sp_pack_2d_Code" }; // 构造函数注入依赖 public InputStorageService( IMapper mapper, IPrintDataMapperFactory mapperFactory, IInputStorageControl inputStorageControl,IConfiguration configuration,ILogger<InputStorageService> logger) { _mapper = mapper; _mapperFactory = mapperFactory; _inputStorageControl = inputStorageControl; _logger = logger; _baseReportPath = configuration["ReportPaths:BaseReportPath"] ?? @"\\10.112.65.20\acme_rpt$\Report\生管報表"; _materialConfigs = materialConfigsControl.LoadMaterialConfigs(configuration); } /// <summary> /// 主逻辑(实现接口方法) /// </summary> public async Task<PDL_PackingResponse> CheckInputStorage(PDL_PackingRequest query) { var response = new PDL_PackingResponse(); try { // 获取批号信息 var lotInfos = await GetLotInfoAsync(query);// await _inputStorageControl.GetLotInfo(_mapper.Map<LotInfo>(query)) if (!lotInfos.Any()) return SetErrorResponse(response, StatusNG, "2", "批号不存在"); // 進行卡點卡控 var spParams = CreateSpParameters(("@LotNum", query.LotNum)); foreach (var procedureName in CheckProcedures) { var errorResponse = await ExecuteCheckProcedure(procedureName, spParams, response); if (errorResponse != null) { return errorResponse; // 遇到首个错误立即返回 } } var spPtint = await _inputStorageControl.GetDataSetProcedure("PDL_Ptint", spParams); if (spPtint?.Tables.Count > 0 && spPtint.Tables[0].Rows.Count > 0) { return SetErrorResponse(response, StatusNG, "2", "此料號未走表面處理流程,不可列印標籤!!!"); } var spEXPDate = await _inputStorageControl.GetDataSetProcedure("PDL_SP_CKPackingEXPDate", spParams); if (spEXPDate?.Tables.Count > 0 && spEXPDate.Tables[0].Rows.Count > 0) { var flagValue = spEXPDate.Tables[0].Rows[0]["Resault"]?.ToString(); if (flagValue == "1") { return SetErrorResponse(response, StatusNG, "2", "此批號有效期已過,無法列印標籤!!!"); } } //取廠別 var lineId = lotInfos.First().LineID?.ToString().Trim() ?? "0"; return lineId switch { "1" => await ProcessLine1Logic(response, query, lotInfos.First().PartNum), "3" => SetErrorResponse(response, StatusNG, "7", "Line3功能待实现"), _ => SetErrorResponse(response, StatusNG, "2", "未獲取到廠別") }; } catch (Exception ex) { _logger.LogError(ex, "系统异常: {Message}", ex.Message); return SetErrorResponse(response, StatusNG, "99", $"系统异常: {ex.Message}"); } } // Line=1业务逻辑处理 private async Task<PDL_PackingResponse> ProcessLine1Logic(PDL_PackingResponse response, PDL_PackingRequest query, string partNum) { // 获取包装数据 var packDataList = await GetPackDataAsync(query); if (!packDataList.Any()) return SetErrorResponse(response, StatusNG, "3", "包裝資料不存在"); var vpartNum = GetPartNum(partNum); var mainConfig = await _inputStorageControl.LoadConfigByPartNum(vpartNum,1); if (mainConfig?.Any() != true) { return SetErrorResponse(response, StatusNG, "3", $"此料號尚未開發自動包裝機程式: {vpartNum}"); } var config = mainConfig.First(); var inputParams = config.HasSpecialJudgment ? await GetSpecialParameters(config, vpartNum, query.LotNum) : new Dictionary<string, string>(); // 获取配置信息 var spName = GetConfigValue(config, "sp_name", inputParams) as string; var labelPath = GetConfigValue(config, "template_path", inputParams) as string; var related = GetConfigValue(config, "related_num", inputParams) as string; var resultFields = GetConfigValue(config, "result_fields", inputParams) as List<string>; var fieldRenames = GetConfigValue(config, "field_rename", inputParams) as Dictionary<string, string> ?? new Dictionary<string, string>(); // 提供默认值; if (string.IsNullOrEmpty(spName) || string.IsNullOrEmpty(labelPath) || string.IsNullOrEmpty(related) || resultFields == null) { return SetErrorResponse(response, StatusNG, "3", "未获取到完整配置信息(存储过程名/模板路径/结果字段)"); } // 执行存储过程 var spParams = CreateSpParameters((" @LotNum", query.LotNum)); var spResult = await _inputStorageControl.GetDataSetProcedure(spName, spParams); if (spResult?.Tables.Count == 0 || spResult.Tables[0].Rows.Count == 0) { return SetErrorResponse(response, StatusNG, "3", "存储过程无返回数据"); } // 使用工厂创建映射器 var mapper = _mapperFactory.Create(vpartNum); var printData = mapper.Map(spResult.Tables[0], resultFields, fieldRenames, vpartNum); // 映射打印数据 response.StatusCode = "1"; response.CheckResult = StatusOK; response.Message = "返回成功"; response.LabelPath = Path.Combine(_baseReportPath, labelPath.Trim()); response.Related = related; response.PackData = packDataList; //response.PrintData = MapPrintData(spResult.Tables[0], resultFields, fieldRenames, vpartNum); response.PrintData = printData; return response; } // 獲取料號前4碼 private string GetPartNum(string partNum) => partNum.Length >= 4 ? partNum.Substring(0, 4) : partNum; // 异步获取批号信息 private async Task<List<LotInfo>> GetLotInfoAsync(PDL_PackingRequest query) { var lotInfo = _mapper.Map<LotInfo>(query); var result = await _inputStorageControl.GetLotInfo(lotInfo); return result?.ToList() ?? new List<LotInfo>(); } // 异步获取包装数据 private async Task<IEnumerable<PackingListDtl>> GetPackDataAsync(PDL_PackingRequest query) { var packDtl = _mapper.Map<PackingListDtl>(query); return await _inputStorageControl.GetPDL_PackData(packDtl) ?? Enumerable.Empty<PackingListDtl>(); } // 通用检查方法(提取重复逻辑) async Task<PDL_PackingResponse> ExecuteCheckProcedure( string procedureName, IEnumerable<SqlSugar.SugarParameter> parameters, PDL_PackingResponse response ) { // 类型匹配:parameters 直接递给 GetDataSetProcedure var dataSet = await _inputStorageControl.GetDataSetProcedure(procedureName, parameters); if (dataSet?.Tables.Count > 0 && dataSet.Tables[0].Rows.Count > 0) { var firstRow = dataSet.Tables[0].Rows[0]; var flagValue = firstRow["Flag"]?.ToString(); if (flagValue == "1") { return SetErrorResponse(response, StatusNG, "2", firstRow["Notes"]?.ToString()); } } return null; // 检查通过返回 null } // 配置获取逻辑 public object GetConfigValue(PackingMainConfig config, string configType, Dictionary<string, string> inputParams) { // 1. 优先匹配非默认规则 foreach (var rule in config.ConditionRules.Where(r => !r.IsDefault)) { if (inputParams.TryGetValue(rule.ConditionType, out string inputValue) && IsConditionMatch(rule.ConditionValue, inputValue)) { if (rule.ResultConfigs.TryGetValue(configType, out object matchedValue)) { _logger.LogInformation("匹配规则: {ConditionType}={ConditionValue}, 值: {Value}", rule.ConditionType, rule.ConditionValue, matchedValue); return matchedValue; } } } // 2. 匹配默认规则 var defaultRule = config.ConditionRules.FirstOrDefault(r => r.IsDefault); if (defaultRule?.ResultConfigs.TryGetValue(configType, out object defaultValue) == true) { _logger.LogInformation("使用默认规则, 值: {Value}", defaultValue); return defaultValue; } // 3. 回退到任意匹配的规则 foreach (var rule in config.ConditionRules) { if (rule.ResultConfigs.TryGetValue(configType, out object fallbackValue)) { _logger.LogInformation("使用后备规则: {ConditionType}, 值: {Value}", rule.ConditionType, fallbackValue); return fallbackValue; } } _logger.LogWarning("未找到 {ConfigType} 的配置值", configType); return null; } // 条件匹配逻辑封装 private bool IsConditionMatch(string conditionValue, string inputValue) { if (conditionValue.StartsWith("[", StringComparison.Ordinal) && conditionValue.EndsWith("]", StringComparison.Ordinal)) { var validValues = conditionValue.Trim('[', ']') .Split(',') .Select(v => v.Trim().Trim('\'')) .ToList(); return validValues.Contains(inputValue); } return inputValue == conditionValue; } /// <summary> /// 快速创建存储过程参数列表 /// </summary> private List<SugarParameter> CreateSpParameters(params (string Name, object Value)[] parameters) { return parameters.Select(p => new SugarParameter(p.Name, p.Value)).ToList(); } // 获取特殊料号参数 private async Task<Dictionary<string, string>> GetSpecialParameters(PackingMainConfig config, string partNum, string lotNum) { // 创建用于存储特殊参数的字典 var specialParams = new Dictionary<string, string>(); // 仅处理特定PartNum的逻辑 if (partNum == "2866") { // 准备存储过程参数 var spParams = CreateSpParameters(("@LotNum", lotNum)); // 调用存储过程获取数据(添加空值检查,避免NullReferenceException) var specialDs = await _inputStorageControl.GetDataSetProcedure(config.SpecialCheckSpName, spParams); // 验证数据集和表结构有效性 if (specialDs?.Tables.Count > 0 && specialDs.Tables[0].Rows.Count > 0) { var dataRow = specialDs.Tables[0].Rows[0]; // 从数据行提取值,使用空合并运算符确保非null specialParams["flagDummy"] = dataRow["FlagDummy"]?.ToString() ?? string.Empty; specialParams["pdFamily"] = dataRow["pd_family"]?.ToString() ?? string.Empty; } } // 返回填充后的参数字典(无数据返回空字典而非null) return specialParams; } // 设置错误响应 private PDL_PackingResponse SetErrorResponse(PDL_PackingResponse response, string checkResult, string statusCode, string message) { response.CheckResult = checkResult; response.StatusCode = statusCode; response.Message = message; return response; } } } // 数据映射层 using System.Data; using System.Dynamic; using MES.Application.InpuStorage.WInterface; using MES.Domain.Entities; using MES.Domain.InpuStorage.WInterface; using MES.Shared.DTOs.Requests.InpuStorage; using MES.Shared.DTOs.Responses.InputStorage; namespace MES.Application.InpuStorage.Repository { // 映射器工厂 public interface IPrintDataMapperFactory { IPrintDataMapper Create(string partNum); } public class PrintDataMapperFactory : IPrintDataMapperFactory { public IPrintDataMapper Create(string partNum) => partNum switch { "5808" => new Map5808LabelData(), _ => new MapPrintData() }; } // 通用映射器 public class MapPrintData : IPrintDataMapper { public List<object> Map(DataTable dataTable, List<string> fields, Dictionary<string, string> fieldRenames, string partNum) { return dataTable.AsEnumerable().Select(row => { dynamic expando = new ExpandoObject(); var dict = (IDictionary<string, object>)expando; foreach (var field in fields) { var targetField = fieldRenames.GetValueOrDefault(field, field); dict[targetField] = row[field]?.ToString() ?? "N/A"; } return expando; }).ToList(); } } // 特殊料号映射器 public class Map5808LabelData : IPrintDataMapper { public List<object> Map(DataTable dataTable, List<string> fields, Dictionary<string, string> fieldRenames, string partNum) { return dataTable.AsEnumerable().Select(row => { dynamic expando = new ExpandoObject(); var expandoDict = expando as IDictionary<string, object>; // 处理配置的原始字段(应用重命名) foreach (string sourceField in fields) { // 跳过需要特殊处理的字段 if (sourceField == "Remark" || sourceField == "MARK2" || sourceField == "bar_unit_qty" || sourceField == "llpiece" || sourceField == "ShortPartnum" || sourceField == "customer_name" || sourceField == "cust_part" || sourceField == "seq_no" || sourceField == "tnum") continue; string targetField = fieldRenames.ContainsKey(sourceField) ? fieldRenames[sourceField] : sourceField; // 确保字段存在 object value = dataTable.Columns.Contains(sourceField) ? row[sourceField]?.ToString().Trim() : "N/A"; expandoDict[targetField] = value; } // 2. 特殊字段换逻辑(复刻VB) // 获取源值 string remark = dataTable.Columns.Contains("Remark") ? row["Remark"]?.ToString().Trim() ?? "" : ""; string mark2 = dataTable.Columns.Contains("MARK2") ? row["MARK2"]?.ToString().Trim() ?? "" : ""; string barUnitQty = dataTable.Columns.Contains("bar_unit_qty") ? row["bar_unit_qty"]?.ToString().Trim() ?? "" : ""; string llpiece = dataTable.Columns.Contains("llpiece") ? row["llpiece"]?.ToString().Trim() ?? "" : ""; string shortPartNum = dataTable.Columns.Contains("ShortPartnum") ? row["ShortPartnum"]?.ToString().Trim() ?? "" : ""; string customer_name = dataTable.Columns.Contains("customer_name") ? row["customer_name"]?.ToString().Trim() ?? "" : ""; string cust_part = dataTable.Columns.Contains("cust_part") ? row["cust_part"]?.ToString().Trim() ?? "" : ""; string seq_no = dataTable.Columns.Contains("seq_no") ? row["seq_no"]?.ToString().Trim() ?? "" : ""; string tnum = dataTable.Columns.Contains("tnum") ? row["tnum"]?.ToString().Trim() ?? "" : ""; // 3. 计算换字段 // LREMARK换 string lremark = remark == "LASER MARK" ? "LASER MARK" : ""; // PB/NON换 string pbValue = ""; string nonHfValue = ""; switch (mark2) { case "1": pbValue = "Pb"; nonHfValue = "Non-HF"; break; case "2": pbValue = "Pb"; break; case "3": nonHfValue = "Non-HF"; break; } // 复合字段 string CustPartNum = $"{customer_name}({cust_part})"; string xOutValue = $"{barUnitQty}/{llpiece}"; string mftValue = $"({shortPartNum})"; string total = $"{seq_no}/{tnum}"; // 4. 添加换字段(应用重命名) // 特殊字段映射 AddFieldWithRename(expandoDict, "CUSTPARTNUM", CustPartNum, fieldRenames); AddFieldWithRename(expandoDict, "TOTALPAGE", total, fieldRenames); AddFieldWithRename(expandoDict, "LREMARK", lremark, fieldRenames); AddFieldWithRename(expandoDict, "PB", pbValue, fieldRenames); AddFieldWithRename(expandoDict, "NON", nonHfValue, fieldRenames); AddFieldWithRename(expandoDict, "X_OUT", xOutValue, fieldRenames); AddFieldWithRename(expandoDict, "MFT", mftValue, fieldRenames); return expando; }).ToList(); } private void AddFieldWithRename(IDictionary<string, object> dict, string fieldName, object value, Dictionary<string, string> fieldRenames) { string targetField = fieldRenames.ContainsKey(fieldName) ? fieldRenames[fieldName] : fieldName; dict[targetField] = value; } } } SELECT * FROM PackingMainConfig 1 1 2866 1 PDL_PackingCheck 2866系列物料配置 NULL NULL 2 1 5808 0 5808系列物料配置 NULL NULL SELECT * FROM PackingConditionRule 1 1 flagDummy Y 1 0 2 1 pdFamily MMC 2 0 3 1 3 1 4 2 1 1 SELECT * FROM PackingResultConfig 1 1 result_fields [“PartNum”, “SSLotNum”, “CustomerPartNum”, “ShortPartnum”, “TotalDummyStrip”, “SerialNum” , “Page” ] 2 1 sp_name sp_PDL_Tag_Black2866 3 1 template_path pdl_Tag_2866_Dummy.btw 4 1 field_rename {“PartNum”: “PartNum”,“SSLotNum”: “SSLotNum”, “CustomerPartNum”: “CustomerPartNum”,“ShortPartnum”: “SHORT”,“TotalDummyStrip”: “STR”, “SerialNum”: “SerialNum”, “Page”: “TOTALPAGE”} 5 2 result_fields [“ShortPartNum”, “Item”, “BarCode2”, “BarCode3”, “PartNum”, “Xout1”, “Xout2”, “Xout3”, “MFG_Date”, “Expired_Date”, “Total”, “Yield”, “PKG_code”, “SerialNum”, “Page” ] 6 2 sp_name sp_PDL_Tag_Black2866 7 2 template_path pdl_Tag_2866_MMC.btw 8 2 field_rename {“ShortPartNum”: “SHORTPARTNUM”,“PartNum”: “FACPARTNUM”, “Xout1”: “XOUT1”,“Xout2”: “XOUTT”,“Xout3”: “XOUT3”, “Expired_Date”: “EXDATE”, “PKG_code”: “PKGCODE”, “Page”: “TOTALPAGE”} 9 3 result_fields [ “ShortPartNum”, “Item”, “BarCode2”, “BarCode3”, “PartNum”, “Xout1”, “Xout2”, “Xout3”, “Xout4”, “Xout5”, “Xout6”, “Xout7”, “Xout8”, “Xout9”, “Xout10”, “Xout11”, “Xout12”, “Xout13” , “Xout14”, “Xout15”, “Xout16”, “Xout17”, “Xout18” , “MFG_Date”, “Expired_Date”, “Total”, “Yield”, “PKG_code”, “SerialNum”, “Page” ] 10 3 sp_name sp_PDL_Tag_Black2866 11 3 template_path pdl_Tag_2866.btw 12 3 field_rename {“ShortPartNum”: “SHORTPARTNUM”,“PartNum”: “FACPARTNUM”, “Xout1”: “XOUT1”,“Xout2”: “XOUTT”,“Xout3”: “XOUT3”,“Xout4”: “XOUT4”,“Xout5”: “XOUT5”,“Xout6”: “XOUT6”,“Xout7”: “XOUT7”,“Xout8”: “XOUT8”,“Xout9”: “XOUT9”,“Xout10”: “XOUT10”,“Xout11”: “XOUT11”,“Xout12”: “XOUT12”,“Xout13”: “XOUT13”,“Xout14”: “XOUT14”,“Xout15”: “XOUT15”,“Xout16”: “XOUT16”,“Xout17”: “XOUT17”,“Xout18”: “XOUT18”, “Expired_Date”: “EXDATE”, “PKG_code”: “PKGCODE”, “Page”: “TOTALPAGE”} 13 1 related_num SerialNum 14 2 related_num SerialNum 15 3 related_num SerialNum 16 4 result_fields [ “T2Lotnum”, “customer_name”, “cust_part”, “datecode”, “unit_qty”, “vendercode”, “Remark”, “MARK2”, “bar_unit_qty”,“llpiece”, “ShortPartnum”, “Strips”, “grossqnty”, “packingdate”, “expired_date”, “userid”, “seq_no”, “tnum” , “SerialNum”, “mftdate”, “IsBack”, “BackNo”, “CODE2D” , “scpcode” ] 17 4 sp_name sp_PDL_5808表身標籤 18 4 template_path PDL_5808表身標籤.btw 19 4 field_rename {“datecode”: “DATECODE”, “expired_date”: “EXPDATE”,“T2Lotnum”: “LOTNUM”,“packingdate”: “PACKINGDATE”,“userid”: “USERID”,“Strips”: “STRIP”,“unit_qty”: “UNIT_QTY”,“vendercode”: “VENDOR_CODE”,“grossqnty”: “GROSS”,“mftdate”: “MFGDATE”,“CODE2D”: “2DCODE”,“scpcode”: “SCPCODE”} 20 4 related_num SerialNum 三張配置表,表數量太多,不利於維護,且字段用了json,複雜度高,留意怎麼設計改善
最新发布
12-20
要将一个DaTaTable换为List<T>,可以使用以下步骤: 1. 创建一个类来表示DaTaTable中的每一行数据。这个类应该包含与DaTaTable中的列对应的属性。 2. 创建一个List<T>对象,其中T是第一步中创建的类。 3. 使用foreach循环遍历DaTaTable中的每一行数据。 4. 在循环中,创建T类型的对象,并将DaTaTable中的每一列的值赋值给T对象的相应属性。 5. 将T对象添加到List<T>中。 6. 返回List<T>对象。 以下是一个示例代码: ``` public class MyDataClass { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } } public List<MyDataClass> ConvertDataTableToList(DataTable dt) { List<MyDataClass> list = new List<MyDataClass>(); foreach (DataRow row in dt.Rows) { MyDataClass obj = new MyDataClass(); obj.Id = Convert.ToInt32(row["Id"]); obj.Name = row["Name"].ToString(); obj.Description = row["Description"].ToString(); list.Add(obj); } return list; } ``` 在这个示例中,我们创建了一个名为MyDataClass的类来表示DaTaTable中的每一行数据。我们还创建了一个名为ConvertDataTableToList的方法,该方法接受一个DataTable对象作为参数,并将其换为List<MyDataClass>对象。在方法中,我们使用foreach循环遍历DaTaTable中的每一行数据,并为每一行数据创建一个MyDataClass对象。然后,我们将DaTaTable中的每一列的值赋值给MyDataClass对象的相应属性,并将MyDataClass对象添加到List<MyDataClass>中。最后,我们返回List<MyDataClass>对象。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值