MetaDapper:使用正确的工具轻松实现数据映射和转换
已发表: 2022-03-11数据转换、翻译和映射绝不是火箭科学,但绝对是乏味的。 即使是简单的数据转换任务(例如,将 CSV 文件读入类实例列表)也可能需要大量代码。 尽管所有这些任务有很多共同点,但它们都“只是不同而已”,需要自己的数据转换方法。
在我们构建的几乎每个系统中,我们都会发现自己需要将数据从一种形式转换为另一种形式,无论是从现有数据存储中导入数据,处理来自传入流的数据,还是从一种格式转换为另一种格式以供内部使用。处理或将数据转换为所需的输出格式。
每次我们这样做时,这项任务似乎都与我们之前多次完成的任务非常相似,但又存在足够的差异,需要我们重新进行数据映射过程,主要是从头开始。
此外,随着最流行的格式和访问它们的技术不断发展,新的格式和技术被引入并获得普及,程序员有义务不断学习新的数据转换和映射技术、库、API 和框架。 随着数据科学服务的不断发展和演变,对专用工具的需求也在扩大。
尽管您可以利用 AutoMapper(将数据从一个对象映射到另一个对象)或 Resharper(重构现有代码)等工具,但无论您做什么,代码编写起来都很乏味,并且始终需要维护。 然后你必须想出一个跨域翻译处理的解决方案——比如将内部代码和键值转换为另一个层或系统的值,将空值转换为默认值,类型转换等。
验证有类似的问题,这些问题可以通过 DataAnnotations 和 jQuery Validation 插件等技术以及大量自定义验证代码来解决。 这些技术的细微差别可能非常微妙。
作为一名高级数据科学家,你告诉自己“一定有更好的方法”。 嗯,事实上,有。 这就是本数据映射教程的内容。
介绍 MetaDapper 数据映射工具
MetaDapper 是一个 .NET 库,旨在最大程度地简化和简化数据转换过程。
MetaDapper 通过以下方式促进数据转换:
- 将数据转换过程的可重复样板部分与每个数据转换任务独有的那些方面分离。
- 提供易于使用、直观的用户界面,用于指定任意复杂度的映射和转换规则。
MetaDapper 将逻辑映射(模式、数据转换和验证)与物理数据映射(与各种文件格式和 API 的转换)分开。 逻辑映射具有一组强大的功能,并允许您使用自己的方法来处理非常特定的需求。 物理映射包括一组丰富的支持格式,这些格式正在不断扩展。 为了配置映射,提供了 MetaDapper Configurator; 一个简单易用的 Windows 可执行文件,用于创建和编辑映射,以及执行它们以进行测试或一次性转换。
将类实例列表转换为 XML 或 CSV 文件、填充 SQL 数据库记录、生成用于填充表的 SQL 脚本、创建电子表格等等,都使用通常可以在几秒钟内创建的相同配置文件完成。
要将 MetaDapper 包含在您的 .NET 程序中,您只需:
- 添加对库的引用
- 实例化 MetaDapper 引擎
- 执行映射,指定源读取器(和任何参数)、目标写入器(和任何参数)和您的配置文件。
成功后,作者将输出转换后的数据。 出错时,异常会返回详细的错误信息,以便您拒绝数据或调整配置。
这是一个简短的数据映射示例:
List<MyClass> result; try { // Instantiate the MetaDapper library. var log = new Log(); var cultureInfo = new CultureInfo("en-US"); var md = new MetaDapper.Engine.MetaDapper(log, cultureInfo); using (var inputStream = new StreamReader(@"C:\myfile.csv")) { md.MapData( new CsvReaderParameters { Log = log, CultureInfo = cultureInfo, InputStream = inputStream.BaseStream, InputEncoding = Encoding.ASCII, FirstRecordIsHeader = false }, new PublicPropertiesWriterParameters { Log = log, CultureInfo = cultureInfo }, @"C:\MyMetaDapperConfiguration.xml", false, out result); } } catch (Exception) { throw; }
MetaDapper “配置器”
MetaDapper 配置器提供了一种直观地完成定义数据结构和转换/映射规则的步骤的方法。 配置器使您能够创建、编辑和执行配置(即,用于测试或一次性转换)。
MetaDapper 的配置器致力于尽可能多地自动化该过程。 例如,在指定字段映射时,源字段和目标字段会在可能的情况下使用名称匹配自动匹配。 此外,在为包含元数据的数据源创建记录定义时,可以通过指向数据源来自动填充字段定义。
创建后,记录定义会维护其与创建它的数据源的链接(如果有),因此如果数据源模式随后发生更改,它可以自动更新。 为几乎没有或没有元数据的数据源配置记录定义时,如果另一个类似的数据源包含元数据,则可以复制该记录定义(连同其元数据),作为新记录定义和然后可以进行编辑以反映两个数据源之间可能存在的任何差异。 在多个数据源的架构和元数据相同的情况下,一个记录定义可用于所有数据源。
简化数据转换过程
让我们更详细地了解数据转换过程中固有的一些挑战,以及 MetaDapper 为开发人员促进和简化这些挑战的方式。
将源数据映射到目标数据
当在维护过程中更改内部或外部结构时,任何依赖这些结构的映射代码也可能需要调整。 这是一个经常需要维护工作的领域,因此无论您使用哪种解决方案,都需要评估维护成本。 例如,如果从 Sale 类中删除了 TotalSale 属性,则需要相应地调整任何相关的映射分配。
使用 MetaDapper,更新映射可能只需几秒钟。 例如,对于类类型,只需单击“从类中导入字段定义”按钮即可将字段刷新为新编译的定义:
类型转换
某些类型转换,例如 Date/Time 和 Number 类型转换,对宿主环境的国际设置很敏感(除非在代码中明确指定)。 因此,在具有不同国际设置的新服务器上部署应用程序可能会破坏没有考虑到这一点的代码。 例如,日期值“1-2-2014”在美国设置的机器上将解释为 2014 年 1 月 2 日,但在英国设置的机器上解释为 2014 年 2 月 1 日。 MetaDapper 支持所有隐式 .NET 转换,并允许在转换过程中对值进行复杂的重新格式化。 此外,可以在 MetaDapper 读取器、写入器和映射引擎中指定单独的(即独立的)国际设置。
复杂的默认值
有时,需要访问其他系统或需要复杂编码来确定默认值的特定业务规则。 MetaDapper 允许将任意数量的自定义委托方法注册到引擎并用于提供默认值、执行自定义数据转换以及提供自定义字段验证。
条件验证规则
有条件地要求字段值(甚至它们的有效值依赖于其他字段的值)的情况并不少见。 例如,合作伙伴名称和合作伙伴社会保障代码字段可以留空,但如果提供了合作伙伴名称,则必须提供合作伙伴社会保障代码(可能还有其他字段)。 这种类型的条件验证很复杂,在自定义代码中很容易出错。 相比之下,MetaDapper 允许轻松配置这种数据映射关系。 具体来说,记录定义中的字段列表可以在条件强制字段组中列出:

然后在映射中,该组可以与任何字段相关联,如果该字段不为空,则反过来需要提供该组中的所有字段。 例如:
跨域转换映射值
源数据可能包含不一致的值。 例如,称呼字段可能包含“先生”、“先生”、“先生”、“先生”或“M”以及所有女性等价词。 或者货币字段可能包含“$”之类的值,而您的目标格式需要“USD”。 产品代码是可能需要从一个系统转换到另一个系统的值的另一个示例。 MetaDapper 允许规范可重用的“同义词列表”,可用于在映射期间转换值。
定义后,您可以指定同义词组以在任何相关字段映射中使用它:
基于值格式和复杂计算的映射
可能需要使用来自一个或多个字段的值来格式化新值。 例如,源值可能需要用常量修饰(例如sale.PriceEach = "$" + priceEach;
)或者可能需要使用多个字段来生成值(例如sale.Code = code1 + “_” + code2;
)。
MetaDapper 提供格式化/模板功能,允许您使用当前记录中的任何字段构建值,包括字段的子字符串部分或常量值。 格式化后,该值将转换为指定的目标类型(顺便说一下,它不需要是字符串)。
类似地,可以在映射期间执行复杂的计算,对字段值和常数的任意组合使用一整套数学运算符和函数。
验证规则
可以在映射中注册和使用自定义验证委托。 以下是验证字段值是否为整数的自定义方法示例(不将字段的数据类型设为整数):
private static bool ValidateIsInteger( Log log, CultureInfo cultureInfo, object value, ref List<ErrorInfo> errors) { try { Convert.ToInt32(value); } catch (Exception) { return false; } return true; }
该方法将在实例化 MetaDapper 时注册。 然后它可以很容易地应用于任何字段映射定义:
分组、排序和过滤
分组和排序操作通常可以在数据库查询中处理,但并非所有数据源都是数据库。 因此,MetaDapper 支持可在内存中执行的复杂分组和排序操作的配置。
在可能只需要部分源数据的情况下,从非数据库源中过滤可能非常复杂,难以实现和维护。 MetaDapper 支持使用布尔运算符为每条记录的任意数量的字段评估配置复杂的过滤器,并根据需要进行任意深度的操作嵌套。 例如:
上述过滤器等价于以下 C# 代码:
if (sale.TransactionID > “0” AND sale.Currency == “USD” AND (sale.Amount > “3” || sale.Amount == “1”)
嵌套映射
一些映射需要多次传递才能完成数据转换过程。 一些示例包括需要前缀或汇总记录的数据、需要根据字段值或文档结构进行不同映射的数据,或者只是为了隔离复杂映射的不同阶段(即翻译名称、类型转换等)。 为此,MetaDapper 支持任何深度级别的嵌套映射。
格式与结构
作为一种数据映射和转换工具,MetaDapper 的构建允许使用内部读取器和写入器接口读取或写入几乎任何数据格式。 这允许创建非常轻量级的读取器/写入器类,并且只关注特定于格式的细微差别。
读者和作者的行为也尽可能聪明和灵活。 例如,XML 读取器和写入器使用 XPath 来指定在 XML 文件中检索或写入数据的位置。 相同的配置还可用于读取和写入,例如,从非 XML 格式(如 CSV 文件)读取和写入,在这种情况下,XPath 值将被简单地忽略。 同样,如果将不包含 XPath 设置的配置与 XML 读取器或写入器一起使用,则会生成错误。
是的。 正确的。 当然。 (一些真实的数据映射示例)
你持怀疑态度。 而且我不怪你。 软件工具很少是他们声称的那样。 因此,这里有一些实际示例,其中 MetaDapper 已被用于提供运营收益。
一家提供医疗保险管理软件的公司的客户不想填写 Web 表格,但想在电子表格中提供他们的数据。 使用 MetaDapper,将上传的电子表格读入内存、清理数据、验证记录并将结果存储在其数据库中。 他们能够接受来自客户的 Excel 文件,而无需使用 MetaDapper 进行任何人工验证,并为他们发布的每个电子表格模板轻松创建配置文件。
一家大型天然气公司有一个内部应用程序,并希望其管理用户能够下载 Excel 格式的报告。 报告格式可能会定期更改。 MetaDapper 促进了从他们的数据库中生成 Excel 工作表。 更新 Excel 格式只需要更新 MetaDapper 配置文件,无需任何代码更改或重新编译。
一家提供资产管理软件的公司需要一种解决方案,以生成与客户相关的会计数据包格式的财务数据,以便导入这些系统。 使用 ORM 包装器开发了通用会计数据查询,并使用 MetaDapper 对数据进行排序、过滤和映射到每个客户所需的模式和格式。 为每个客户制作一个或多个 MetaDapper 配置,这已成为新客户的主要销售功能。 该产品可以在几分钟内配置(使用 MetaDapper)以支持任何自定义或标准会计包格式,因此每次新销售都包含与基本和现有系统的集成。 同一家公司在各种软件集成项目中使用 MetaDapper,映射和转换数据以及在其系统之间转换内部代码。
一家大型汽车经销商需要将一些 Excel 格式的销售报告添加到他们的一个应用程序中。 报告在不到一个小时的时间内被添加到应用程序中——从开始到结束。
开发人员需要一个与另一个网站上使用的集合相同的美国州表。 MetaDapper 用于从该站点挖掘数据并在几分钟内生成用于填充他的表的 SQL 脚本。
这些只是 MetaDapper 作为数据映射工具经过验证的实用性和价值的几个示例。
包起来
开始更一般地考虑数据转换并开始考虑具有业务规则和无限有用性的数据集需要精神上的跳跃。 MetaDapper 是一个促进和促进这种观点的框架。
无论您是使用 MetaDapper,另一种技术,还是推出自己的数据映射解决方案,这都是对数据转换项目中的一些复杂性和隐藏成本的介绍。 我希望你能从中受益。
(有关 MetaDapper 的更多信息,请通过 [email protected] 联系 MetaDapper 团队。)