如何使用Automapper从DbGeometry转换为String?

时间:2015-08-18 03:10:20

标签: c# entity-framework azure automapper azure-mobile-services

我有一个带有几何列的空间表。我的实体如下:

public class Tile 
{
    public DbGeometry Geometry { get; set; }
}

我正在使用数据传输对象将Tile类返回给我的客户端。我还从我的客户端创建Tiles,所以我想从一个字符串(Geometry的Well Known Text表示)转换为DbGeometry字段。这是我的DTO:

public class TileDto
{
    public String Geometry { get; set; }
}

现在我的第一个想法是创建自定义转换器,如下所示:

public class DbGeometryToStringConverter : ITypeConverter<DbGeometry, string>
{
    public string Convert(ResolutionContext context)
    {
        var geom = (DbGeometry) context.SourceValue;
        return geom.AsText();
    }
}
public class StringToDbGeometryConverter : ITypeConverter<string, DbGeometry>
{
    public DbGeometry Convert(ResolutionContext context)
    {
        var wkt = (string) context.SourceValue;

        var geom = DbGeometry.FromText(wkt);
        if (geom == null || !geom.IsValid) return null;

        return geom;
    }
}

然后我将AutoMapper配置设置为使用以下两者进行映射:

 AutoMapper.Mapper.Initialize(cfg =>
 {
     // Configure our custom type converter for the DbGeometry class
     cfg.CreateMap<DbGeometry, string>().ConvertUsing<DbGeometryToStringConverter>();
     cfg.CreateMap<string, DbGeometry>().ConvertUsing<StringToDbGeometryConverter>();

     cfg.CreateMap<Tile, TileDto>();
     cfg.CreateMap<TileDto, Tile>();
 });

但是这给了我错误:类型'System.String'没有默认构造函数

我尝试使用ResolveUsing方法,但它也给了我一个NullReferenceException。我确保所有列都有一个几何列,所以我不确定它是如何为空。

cfg.CreateMap<Tile, TileDto>()
    .ForMember(tileDto => tileDto.Geometry,
               map => map.ResolveUsing(tile => tile.Geometry.WellKnownValue));

这在Azure应用程序后端的ASP.NET应用程序中使用,因此调试器因错误而中断的控制器是:

public class TileController : TableController<TileDto>
{
    private DatabaseContext _context;

    protected override void Initialize(HttpControllerContext controllerContext)
    {
        base.Initialize(controllerContext);
        _context = new DatabaseContext();
        DomainManager = new TileDtoToTileMappedEntityDomainManager(_context, Request, Services);
    }

    public SingleResult<TileDto> GetTile(string id)
    {
        // MY ERROR HAPPENS HERE
        return Lookup(id);
    }
}

public class TileDtoToTileMappedEntityDomainManager : MappedEntityDomainManager<TileDto, Tile>
{
    public override SingleResult<TileDto> Lookup(string id)
    {
        return LookupEntity(t => t.Id == id);
    }

    public override Task<TileDto> UpdateAsync(string id, Delta<TileDto> patch)
    {
        return UpdateEntityAsync(patch, id);
    }

    public override Task<bool> DeleteAsync(string id)
    {
        return DeleteItemAsync(id);
    }
}

我正在使用AutoMapper 3.2.1,因为Azure Mobile Service SDK依赖于它。我正在尝试在我的Azure移动服务中为我的实体创建DTO,所以我不完全确定这是我的AutoMapper配置是错误的还是我的实体是如何设置的。我按照this post中的步骤创建了DTO。我需要在AutoMapper中进行配置更改才能使其正常工作吗?

1 个答案:

答案 0 :(得分:1)

感谢@Backs,问题在于我的AutoMapper配置。使用MapFrom方法而不是ResolveUsing就可以了。

这是我的配置:

AutoMapper.Mapper.Initialize(cfg =>
{
    cfg.CreateMap<Tile, TileDto>()
       .ForMember(tileDto => tileDto.Geometry,
                  map => map.MapFrom(tile => tile.Geometry.AsText()));

    cfg.CreateMap<TileDto, Tile>()
       .ForMember(tile => tile.Geometry,
                  map => map.MapFrom(tileDto => DbGeometry.FromText(tileDto.Geometry)));

    cfg.CreateMap<Tile, TileDto>();
    cfg.CreateMap<TileDto, Tile>();
});