Использование LINQ с разными слоями означает, что я не могу получить доступ к определенному типу

У меня есть 3 слоя в моем решении:

  • DAL (который обращается к моей БД с помощью LINQ)
  • Бизнес-уровень
  • Винформ

В моем DAL я возвращаю List с определенным типом из моей БД, и я делаю то же самое в своем BLL.

Когда я хочу использовать свою функцию в своем пользовательском интерфейсе, я получаю сообщение об ошибке:

Тип «Резервирование» определен в сборке, на которую нет ссылок...

Теперь я хочу избежать необходимости ссылаться на свой DAL в своем пользовательском интерфейсе.

Поскольку я новичок в этом и не смог найти четкого ответа в Интернете, может ли кто-нибудь помочь мне, пожалуйста?

Моя функция DAL

public static List<Reservation> SelectListReservation()
{
    try
    {
        List<Reservation> lstReservation = new List<Reservation>();
        lstReservation = oExamenSgbdEntities.Reservations.ToList();
        return lstReservation;
    }
    catch (Exception e)
    {
        throw e;
    }
}

Моя функция BLL

public static List<DataAccess.Reservation> GetListReservation()
{
    try
    {
        List<DataAccess.Reservation> lstToReturn = new List<Reservation>();
        lstToReturn = GetListReservation();
        return lstToReturn;
    }
    catch (Exception e)
    {
        throw e;
    }
}

Как я вызываю свою функцию BL в своем пользовательском интерфейсе:

var lstRes = Manage.GetListReservation();

person Jeremy    schedule 14.12.2018    source источник
comment
Для чего нужны бессмысленные блоки try…catch…throw?   -  person Uwe Keim    schedule 14.12.2018
comment
Он не знает, что вы можете сказать отладчику сломаться при первом исключении.   -  person Matthew Whited    schedule 14.12.2018
comment
кстати, если вы делаете это, вы должны просто сделать throw;, а не throw e;   -  person Matthew Whited    schedule 14.12.2018
comment
@MatthewWhited прав, throw e сбросит трассировку стека.   -  person Lews Therin    schedule 14.12.2018
comment
Должен ли я никогда не использовать throw e тогда? Или я должен использовать его только в определенном слое? Я просто хочу показать ошибки в MessageBox в конце.   -  person Jeremy    schedule 14.12.2018


Ответы (3)


Судя по деталям вашего вопроса, вы используете Традиционная многоуровневая архитектура. В этой архитектуре уровень пользовательского интерфейса зависит от BLL, а BLL зависит от DAL. Это должна быть ваша ссылочная структура: проект пользовательского интерфейса ссылается на проект BLL, а проект BLL ссылается на проект DAL.

Для вас это означает, что вы не можете использовать классы из DAL в своем пользовательском интерфейсе; пользовательский интерфейс не должен знать реализацию DAL, потому что DAL может измениться (например, при переходе из базы данных SQL Server в базу данных Oracle). Итак, чтобы получить данные из DAL в BLL, вам нужно создать класс модели в вашем BLL и сопоставить с ним все данные из класса DAL.

Например, в вашем BLL вам нужно добавить класс ReservationModel, который будет сопоставляться с классом Reservation в вашем DAL:

public class ReservationModel
{
    // Add the same properties that are in the Reservation class in 
    // the DAL to this class. The properties below are just for example
    public int ReservationId { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    public int CustomerId { get; set; }
}

Затем в BLL измените метод GetListReservation(), чтобы он возвращал ReservationModel со всеми данными, сопоставленными из класса Reservation в DAL:

public static List<ReservationModel> GetListReservation()
{
    var reservationModels = new List<ReservationModel>();

    foreach (var reservation in SelectListReservation())
    {
        reservationModels.Add(new ReservationModel
        {
            // Again, these are made-up properties for illustration purposes
            ReservationId = reservation.ReservationId,
            StartDate = reservation.StartDate,
            EndDate = reservation.EndDate,
            CustomerId = reservation.CustomerId
        });
    }

    return reservationModels;
}
person Lews Therin    schedule 14.12.2018
comment
Мне нравится этот ответ. Однако я считаю, что классы DAL могут использоваться пользовательским интерфейсом без явной ссылки на DAL, если они скрыты за интерфейсом. - person JuanR; 14.12.2018
comment
@JuanR Я мог бы что-то упустить, но я не думаю, что это возможно просто потому, что где будет интерфейс? Если он находится в DAL, пользовательский интерфейс его не увидит; если он находится в BLL, DAL его не увидит; если он находится в пользовательском интерфейсе, DAL и BLL его не увидят. BLL должен быть посредником между пользовательским интерфейсом и DAL (что хорошо, потому что вы можете заменить DAL или пользовательский интерфейс и по-прежнему использовать основную бизнес-логику). - person Lews Therin; 14.12.2018
comment
В прошлом я делал отдельную сборку для интерфейсов. Затем на эту сборку могут ссылаться все остальные (например, SomeProject.Core). - person JuanR; 14.12.2018
comment
Рад, что смог помочь. - person Lews Therin; 14.12.2018

Если вы включаете DAL, BL и P, ваш метод BL не может возвращать тот же тип, что и ваш DAL.

P использует BL, а BL использует DAL

Поэтому P абстрагируется от DAL

Резервирование должно использоваться только BL, если оно содержится в DAL.

Разделите тип DAL и тип BL или выберите другую архитектуру.

person MrVoid    schedule 14.12.2018

Одним из решений является создание библиотеки объектов передачи данных (DTO), которые обертывают объекты из уровня данных, поскольку они определены в отдельной сборке. Затем бизнес-уровень может выполнять вызовы базы данных и преобразовывать результаты в эти новые классы.

Это разрушает зависимость между уровнем представления и уровнем данных, а также позволяет настраивать то, что вы выставляете из Данные -> Бизнес и/или Бизнес -> Презентация (вы можете объединить несколько объектов из базы данных в один, и вы может выставлять гораздо меньшие объекты, где это возможно).

Подробнее об этом можно прочитать здесь: Создать объекты передачи данных (DTO)

person Rufus L    schedule 14.12.2018