【问题标题】:How to use autoMapper for datatables to list?如何使用 autoMapper 列出数据表?
【发布时间】:2020-09-01 19:00:48
【问题描述】:

我想我的代码中遗漏了一些导致此错误的内容:AutoMapperMappingException: Missing type map configuration or unsupported mapping. 这是我第一次尝试使用 autoMapper 从数据表中填充我的 dto。所以我从How do I use automapper to map a dataset with multiple tables 中找到了一个例子。所以这是我的代码:

public class ContractController : ApiController
    {
        private readonly IMapper _mapper;

        public ContractController()
        {
            var mapperConfig = new MapperConfiguration(x =>
                x.CreateMap<IDataReader, ContractListDto>());
            _mapper = mapperConfig.CreateMapper();
        }

        [Route("api/Sales/ContractsList")]
        [HttpGet]
        public IHttpActionResult  Get()
        {
            var salesHelper = new SalesHelper(enmSaleDocType.enmSaleDocType_SaleContract,
                enmSaleAfterSaleMode.enmSaleAfterSaleMode_Sale,
                enmSaleOperationType.enmSaleOperationType_Sales);
            var saleDataTable = salesHelper.GetSales();
            IEnumerable<ContractListDto> contractsDto = null;
            using (var saleDataReader = saleDataTable.CreateDataReader())
            {
                 contractsDto = _mapper.Map<IEnumerable<ContractListDto>>(saleDataReader);
            }
            
            
            return Ok(contractsDto);
        }
    }

我正在使用 api2 dotnet 框架和 automapper 版本 10。所以我无法在 globol.asax 中初始化 automapper。所以我尝试从构造函数中实现这一点,正如您在我的代码中看到的那样。(我可能在那里做错了什么!)。最后我在这里得到错误:

using (var saleDataReader = saleDataTable.CreateDataReader())
            {
                 contractsDto = _mapper.Map<IEnumerable<ContractListDto>>(saleDataReader);
            }

当我尝试映射时。感谢阅读。

【问题讨论】:

  • 为什么要使用 AutoMapper? GetSales 是做什么的?如果您使用例如 EF Core 或Dapper,则不需要映射任何内容。您也不需要处理原始数据读取器
  • AutoMapper 不需要从数据库加载数据。它旨在执行非常具体、简单的映射。人们一直在尝试将它用于从未打算做的事情,通常会得到更多代码,而不是直接执行转换。这是这样一种情况。您链接到的答案(不是示例)中的代码更长,而不仅仅是为行的内容显式创建一个新对象,而且更容易出错。
  • 您可以使用例如 [LINQ to DataTable[(docs.microsoft.com/en-us/dotnet/framework/data/adonet/…) 并通过非常简单的 LINQ 查询获取您的对象,例如 someTable.AsEnumerable().Select(row=&gt;new Contract{ ID=row.Field&lt;int&gt;("ID"), Date=row.Field&lt;DateTime&gt;("Date"),...{)
  • 因为我没有使用实体框架或dapper,在GetSales我正在调用其他使用ado.net的项目的数据访问,由于某些原因我什至无法将其重构为最新版本...
  • EF Core 和 Dapper 也使用 ADO.NET。 EF 在 ASP.NET 中运行良好,而 Dapper 适用于所有运行时。不管你怎么看,AutoMapper 根本不适合这个。 GetSales() 是做什么的,它返回什么,为什么不使用 Dapper 替换该代码?一个简单的connection.Query&lt;ContractListDTO&gt;(sqlQuery); 将执行查询在一次调用中映射结果。

标签: c# asp.net ado.net asp.net-web-api2 automapper


【解决方案1】:

您不能使用 Automapper,因为它在这里查看一个对象的属性,并在那里查看另一个对象的属性,然后将它们复制过来。 DataRow 没有任何有趣的属性

当你加载一个基础的弱类型数据表时:

var myDataTable = new DataTable();
myDataDapter.Fill(myDatatable);

您有一组 DataRow 对象。当你想从数据行中取出一项数据时,有多种方法可以得到它,但根过程总是相同的;您可以通过将索引器传递给集合并转换结果来将其从它所在的对象数组中取出:

var row1 = myDatatable.Rows[0];

var personName = row1["PersonName"] as string; 

写同样的东西有很多替代方法,但最终这些数据只是存在于一个数组中,并由 string/int 索引,它需要强制转换才能有用。 DataRow 没有返回字符串的 PersonName 属性; AUtomapper 旨在使用返回字符串的 PersonName 属性。

正如 Panagiotis 在 cmets 中指出的那样,您需要对数据行做一些事情以使其具有属性,但是您准备一个可以与 Automapper 一起使用的对象所付出的努力程度,您可能也只需跳过 Automapper 并将值直接分配给目标对象

例子

//no
class Person{ 
  public string PersonName 
}
...
foreach(DataRow ro in someDt)
  var p = new Person();
  p.PersonName = ro["PersonName"] as string;

  var p = mapper.Map<PersonDto>(p);
  

所有创建人员类并分配给它的 PersonName 只是为了让 Automapper 有一些可以映射到 PersonDto 的东西 -> 毫无意义!只需新建一个 PersonDto 并直接赋值


我们可以通过一些减少工作量的方式来执行相同的事情,我想这可能有一个用例。如果您想将 DataSet 添加到您的项目中,您可以添加一个新的数据表并在其中指定属性的名称和类型。在代码中,它本身就成为一个类,具有 Automapper 可以使用的属性。实际上,这只是 Visual Studio 编写的一堆代码,例如:

class PersonRow: DataRow

  public string PersonName {
    get{
      return this["PersonName"] as string;
    }
...

即in 为您继承基本 DataRow 并添加属性。这是一种创建数据实体表示的简单方法,它仍然可以像 DataTable/DataRow 一样工作(因为它是继承的).. 所以 dataadapter / ado.net 可以填充它,然后您可以使用命名属性

如果您迫切需要使用 automapper,那将是我的选择;让 VS 为您编写这个无聊的代码“创建一个访问对象内部数组并转换结果的命名属性”。这张图片中的每一个都是一个基本的 DataTable/DataRow,并通过命名属性进行了增强:

(来自文档)

它们比基本 DataTable 好用得多,你可以直接 linq 查询它们 (personDataTable.Select(x => ...)`,你不需要转换任何东西......

【讨论】:

    猜你喜欢
    • 2016-08-14
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 2013-05-09
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多