Как вы можете обращаться с циклическими ссылками при отображении?

Возьмите эту базу данных например

Работник

id - int (PK)имя - варчар

Зарплата

id - int (PK)employee_id - int (FK)количество - плавать

Entity Framework будет генерировать модели, подобные этим:

public partial class Employee
{
    public Employee()
    {
        this.Salaries = new HashSet<Salary>();
    }
    public int id { get; set; }
    public string name { get; set; }
}

public partial class Salary
{
    public int id { get; set; }
    public int employee_id { get; set; }
    public float amount  { get; set; }
    public Employee employee { get; set; }
}

Emplyee ссылается на список своих зарплат, в то время как каждая зарплата указывает, какому сотруднику он принадлежит. Это приводит к проблеме круговой ссылки.

Я следую шаблону хранилища и использую AutoMapper для перевода Employee в EmployeeDTO и Salary в SalaryDTO. Я хочу, чтобы эти DTO хранили информацию о своих детских отношениях. Однако я не хочу делать это рекурсивно. Я мог бы сделать что-то вроде.

public partial class EmployeeDTO
{
    public EmployeeDTO()
    {
        this.Salaries = new HashSet<SalaryChildDTO>();
    }
    public int id { get; set; }
    public string name { get; set; }
}

public partial class SalaryChildDTO
{
    public int id { get; set; }
    public float amount  { get; set; }
}

Но это станет кошмаром обслуживания.

Как я могу сказать AutoMapper отображать только одного потомка или достичь аналогичной цели?

Ответы на вопрос(2)

потому что нашел простой способ управления.

public partial class EmployeeDTO
{
    public int id { get; set; }
    public string name { get; set; }
    public virtual IEnumerable<SalaryChildDTO> Salaries { get; set; } //Notice the Virtual
}

public partial class EmployeeChildDTO : EmployeeDTO
{
    [IgnoreMap] //MAGIC!
    public override IEnumerable<SalaryChildDTO> Salaries { get; set; } //Override! :o
}

public partial class SalaryDTO
{
    public int id { get; set; }
    public int employe_id { get; set; }
    public float amount  { get; set; }
    public virtual EmployeeChildDTO Employee { get; set; } //Notice the Virtual once again
}

public partial class SalaryChildDTO : SalaryDTO
{
    [IgnoreMap] //MAGIC!
    public override EmployeeChildDTO Employee { get; set; } //Override! :o
}

Таким образом, единственные изменения в базе данных, которые влияют на дочерние DTO, - это FK!

Я мог бы сделать это другим способом (EmployeeDTO расширяет EmployeeChildDTO) и избежать переопределений, виртуальных и IgnoreMaps, но я хотел оставить основной DTO в качестве базового класса.

 Korijn11 апр. 2014 г., 12:37
Как это сработало в долгосрочной перспективе? Было ли это нормально с точки зрения обслуживания?
 Pluc15 апр. 2014 г., 18:48
@Korijn По другим причинам я вообще не использовал это (или вернулся через некоторое время). Я не буду отмечать этот ответ, так как я не могу дать продолжение.

почему это будет кошмар обслуживания. Некоторое время я делал то же самое, и у меня все работает нормально. Однако следует отметить, что вы все еще хотите, чтобы идентификатор сотрудника находился внутриSalaryChildDTO класс.

 Pluc18 окт. 2012 г., 13:24
Я имею в виду, что если вы вручную сопоставляете EOC POCO с DTO, вам не нужно создавать «ChildDTO», поэтому вы просто заменяете время написания Child DTO написанием ручного отображения
 Kassem17 окт. 2012 г., 22:29
Нет, это все еще не тот же объем работы. В большинстве случаев ваши DTO будут очень похожи на ваши доменные объекты. AutoMapper достаточно умен, чтобы отображать свойства с одинаковыми именами, но также достаточно мощный, чтобы позволить вам настроить отображение между свойствами, когда это не так.
 Pluc17 окт. 2012 г., 21:32
Потому что это удваивает количество классов, которые вы должны изменить вручную, когда вы хотите добавить / изменить модель / базу данных, и количество троек по сравнению с количеством карт, которое мне нужно настроить.
 Pluc17 окт. 2012 г., 22:16
Что мне трудно принять, так это то, что AutoMapper на самом деле не облегчает мою жизнь с точки зрения того, сколько изменений я должен применить, если я внесу изменение в объекте домена. Вместо того, чтобы создавать дочерние классы для каждого DTO в проекте, я мог бы просто выполнить ручное отображение, и это привело бы к почти такой же работе ... Вот почему, в моей голове, ДОЛЖЕН быть другой способ ... Я просто не чувствую, что это правильно ...
 Kassem17 окт. 2012 г., 21:35
Это правда. Но этого нельзя избежать, если вы хотите отделить модель вашего домена от остальной части вашего приложения. Если количество доменных объектов в вашем проекте не в сотнях, то вполне нормально создать DTO или даже несколько DTO, которые имеют отношение к каждой вашей бизнес-операции. А AutoMapper должен сделать вашу жизнь намного проще, чем выполнять все работы по прокладке карты самостоятельно. Необходимость поддерживать изменения в вашем домене и слоях DTO гораздо лучше, чем решать другие проблемы, возникающие в результате использования вашего доменного уровня на уровне пользовательского интерфейса или на уровне обслуживания.

Ваш ответ на вопрос