2016-02-24 5 views
2

Мне сложно понять что-то, что кажется «легкой» проблемой. Я работаю с мобильными приложениями Microsoft Azure .Net, база данных MSSQL, Entity Framework с кодовым кодом и AutoMapper. Так у меня есть следующие объекты:сериализованное свойство сложного типа в dto с linq и automapper

public class Route 
{ 
    public string Id { get; set; } 
    [...] //some other properties 
    public string SerializedGoogleRoute { get; set; } 
} 

public class DtoRoute 
{ 
    public string Id { get; set; } 
    [...] 
    public DtoGoogleRoute GoogleRoute { get; set; } 
} 

public class DtoGoogleRoute 
{ 
    [...] //only strings, ints,... 
} 

Так что я хочу сделать, это: В базе данных спасти GoogleRoute как последовательную строку, поскольку она состоит из множества свойств, и я не нуждаюсь в них в разных колонках - Я просто хочу, чтобы это была сериализованная строка в одном столбце объекта маршрута. Когда объект Route проецируется на объект DtoRoute, я хочу, чтобы GoogleRoute был сериализован и наоборот.

Поскольку я работаю с LINQ/queryables, я ограничен несколькими параметрами отображения AutoMapper (см. AutoMapper wiki). И ни с одним из них я не могу заставить его работать.

Проблемы я облицовочные/что я пробовал: Я не могу сериализовать/десериализации строки в DtoGoogleRoute на отображение (с MapFrom или ConstructProjectionUsing), потому что LINQ, очевидно, не может преобразовать методы JsonConvert.Serialize/десериализации в SQL заявления.

Я пробовал иметь свойство DtoGoogleRoute в объекте Route и свойство string в объекте DtoRoute с помощью getters/seters, выполняющих сериализацию (de). Это почти отлично работает в пользовательском API-контроллере, но из-за фильтра запросов OData приложение azure для мобильных приложений .Net используется в контроллерах таблицы снова, только возвращаемое клиенту свойство serialized string возвращается (поскольку OData/LINQ не знает другого свойства).

Еще один вариант - сделать сложный тип из DtoGoogleRoute с Entity Framework - это отлично работает, но не с AutoMapper, потому что AutoMapper не может обрабатывать сложные типы.

На данный момент я работаю с пользовательским контроллером API, и это работает. Но было бы лучше использовать tablecontrollers, потому что они поддерживают автономную синхронизацию.

Я не представляю себе такую ​​простую вещь (по крайней мере, я думал, что это простая вещь) не может быть сделано или так трудно сделать. Но, возможно, проблема связана со всеми компонентами (tablecontroller, OData, LINQ, EF, AutoMapper).

Я действительно был бы благодарен, если бы кто-то мог помочь.

[EDIT]: Я думаю, что тот факт, что он работает с обычным контроллером api, а не с tablecontroller, имеет какое-то отношение к OData. Я попытался поместить тот же код в метод tablecontroller и в методе контроллера API. при вызове метода контроллера API я могу видеть на сервере, что он просто вызывает эту функцию и возвращает все нужные свойства клиенту (проверяется с помощью скрипача). Но при вызове метода tablecontroller метод tablecontroller «переписывает» URL-адрес URL-адреса OData -> Я думаю, это связано с некоторыми атрибутами EnableQuery или другими OData. Поскольку here (хотя и не AutoMapper, но похоже на аналогичный проект от Microsoft), он говорит, что атрибут EnableQuery вызывается дважды - также когда запрос покидает сервер. И я думаю, что это сокращает свойство GoogleRoute, потому что он не знает об этом свойстве в метаданных OData или что-то в этом роде.

ответ

0

Вы можете достичь его, как это -

internal class RouteToDtoConverter : TypeConverter<Route, DtoRoute> 
{ 
    protected override DtoRoute ConvertCore(Route source) 
    { 
     return new DtoRoute 
     { 
      Id = source.Id, 
      GoogleRoute = JsonConvert.DeserializeObject<DtoGoogleRoute>(source.SerializedGoogleRoute) 
     }; 
    } 
} 

internal class DtoToRouteConverter : TypeConverter<DtoRoute, Route> 
{ 
    protected override Route ConvertCore(DtoRoute source) 
    { 
     return new Route 
     { 
      Id = source.Id, 
      SerializedGoogleRoute = JsonConvert.SerializeObject(source.GoogleRoute) 
     }; 
    } 
} 

public class Route 
{ 
    public string Id { get; set; } 

    public string SerializedGoogleRoute { get; set; } 
} 

public class DtoRoute 
{ 
    public string Id { get; set; } 

    public DtoGoogleRoute GoogleRoute { get; set; } 
} 

public class DtoGoogleRoute 
{ 
    public int MyProperty { get; set; } 
    public int MyProperty2 { get; set; } 
} 


AutoMapper.Mapper.CreateMap<Route, DtoRoute>() 
      .ConvertUsing(new RouteToDtoConverter()); 

AutoMapper.Mapper.CreateMap<DtoRoute, Route>() 
      .ConvertUsing(new DtoToRouteConverter()); 

var res = Mapper.Map<DtoRoute>(new Route 
     { 
      Id = "101", 
      SerializedGoogleRoute = "{'MyProperty':'90','MyProperty2':'09'}" 
     }); 

var org = Mapper.Map<Route>(res); //pass 
+0

привет, спасибо за ваш комментарий. Я уже пробовал использовать конвертер пользовательского типа, но, как указано [здесь] (https: // github.com/AutoMapper/AutoMapper/wiki/Queryable-Extensions), эти typeconverters недоступны для пользователя с запросами расширения. поэтому они работают с Map <>(), но не с ProjectTo <>() - который используется с queryables/linq. –

Смежные вопросы