Я хочу использовать запрашиваемые расширения AutoMapper (.ProjectTo
), но я не могу понять, как это сделать, не копируя код во многие мои свойства объектов базы данных и не дублируя его в проекции.Вот пример, который переопределяет ToString и имеет настраиваемое свойство:
class Claim {
public int Id { get; set; }
public int TypeId { get; set; }
public ClaimType Type { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Name
=> $"{FirstName} {LastName}";
}
class ClaimType {
public int Id { get; set; }
public string Value { get; set; }
public string Abbrev { get; set; }
public override string ToString()
=> Value + (Abbrev != null ? $" ({Abbrev})" : "");
}
class ClaimViewModel {
public int Id { get; set; }
public string Type { get; set; }
public string Name { get; set; }
}
Теперь предположим, что у меня есть две вышеупомянутые модели базы данных и модель представления. Я хочу проецировать Claim на ClaimViewModel в запросе.Единственный способ, которым я знаю, как это сделать, таков:
CreateMap<Claim, ClaimViewModel>()
.ForMember(c => c.ClaimType, x => x.MapFrom(c => c.ClaimType.Value + (c.ClaimType.Abbrev != null ? $" ({c.ClaimType.Abbrev})" : "")))
.ForMember(c => c.Name, x => x.MapFrom(c => $"{c.FirstName} {c.LastName}"));
Очевидно, что это дублирует код свойства Name и метода ClaimType.ToString.Существуют ли какие-либо установленные шаблоны для решения этой проблемы и сохранения кода СУХОЙ?У нас есть много пользовательских свойств и переопределений ToString в наших моделях.Я обнаружил, что могу сделать следующее для свойства Name ... сначала в классе Claim:
public static readonly Expression<Func<Claim, string>> NameExpr = (c) => $"{c.FirstName} {c.LastName}";
public string Name => NameExpr(this);
А затем в сопоставлении сделать это:
.ForMember(c => c.Name, x => x.MapFrom(Claim.NameExpr));
Thisкажется вполне подходящим для этого очень простого случая, но он не работает для ситуаций со ссылками на внешние ключи, таких как метод ClaimType.ToString.В этом случае я мог бы поместить выражение в Claim и сослаться на него в сопоставлении Claim, но в тот момент, когда мне нужно было проецировать ClaimType в ClaimTypeViewModel, мне пришлось бы продублировать код.Или, если бы существовала другая модель базы данных, ссылающаяся на модель ClaimType, у меня возникла бы та же проблема.
Если ответ имеет значение, ORM будет EF Core @ 2.1.3.
РЕДАКТИРОВАТЬ: Я не понял этого, когда писал этот вопрос, но приведенное выше отображение будет работать без конфигурации ForMember, но я заметил в SQL Profiler, что запрос будет откатывать каждый столбец в Claim и ClaimTypeмодели, а не только необходимые столбцы.Это хорошо, но мне действительно нужен бонус производительности ProjectTo только для того, чтобы вытащить нужные столбцы.