首页 > 解决方案 > 使用表达式和 linq 选择映射重构

问题描述

我的目标是以可扩展的方式处理一些到 DTO 的映射,从而减少一些样板文件。我必须在这里使用 Iqueryable,不能只调用 .toList()。

这件作品有效。(另请注意,示例中显示了 BusinessUnit 的所有属性,尽管我还有大约 25 个要映射的对象 - 有些很大)

    //class BusinessUnitController
    private IQueryable<BusinessUnitDTO> BuildProjections()
    {

        IQueryable<BusinessUnitDTO> results = DataContext.BusinessUnits
            .AsNoTracking()
            .Select(BusinessUnitMapper.EntityToMessage);

        return results;
    }

    //Class businessUnitMapper
    public static Expression<Func<BusinessUnit, BusinessUnitDTO>> EntityToMessage = from => new BusinessUnitDTO
    {
        Id = from.Id,
        Name = from.Name,
        Code = from.Code
    };

不幸的是,当我还需要能够在其他用例中调用它时,它的规模并没有那么大。所以我也有以下的点点滴滴。

public BusinessUnitDTO Map(BusinessUnit from)
    {
        BusinessUnitDTO result = null;

        if (from != null)
        {
            result = new BusinessUnitDTO
            {
                Id = from.Id,
                Name = from.Name,
                Code = from.Code
            };
        }
        return result;
    }

     public static BusinessUnitDTO MapToMessage(this BusinessUnit businessUnit)
    {
        BusinessUnitMapper mapper = new BusinessUnitMapper();

        return mapper.Map(businessUnit);
    }

必须有一种方法可以在这两种情况下重用这个映射。我试图直接调用分机.. 示例:

.Select(BusinessUnit.MapToMessage()); 但是,这不起作用,因为它无法将其转换为 SQL。

那么我如何为这两个功能用例提供服务,同时仍然只需要构建一次映射呢?有什么办法可以使用泛型来大大减少这里的样板文件吗?

标签: lambdalinq-to-sqlrefactoringexpression

解决方案


编译映射器以供客户端使用:

#class BusinessUnitMapper
public static Func<BusinessUnit, BusinessUnitDTO> BU2DTO = EntityToMessage.Compile();

public BusinessUnitDTO Map(BusinessUnit from)
    {
        BusinessUnitDTO result = null;

        if (from != null)
        {
            result = BU2DTO(from);
        }
        return result;
    }

我无法抗拒单行:

public BusinessUnitDTO Map(BusinessUnit from) => from != null ? BU2DTO(from) : default;

推荐阅读