Циклические зависимости в многоуровневой архитектуре Asp.Net MVC

Я новичок в Asp.Net MVC и хочу разделить свой проект на многоуровневую архитектуру, имеющую 1- Проект MVC (уровень пользовательского интерфейса уровня представления) 2- Слой бизнес-логики BLL (здесь я хочу проверить модель представления данных и преобразовать модель представления в модель базы данных с помощью автоматического сопоставления, а затем хочу отправить обратно модель представления путем обратного преобразования с помощью слоя автоматического сопоставления с пользовательским интерфейсом (проект MVC) 3- Уровень доступа к данным, имеющий контекст БД репозиториев и т. д., на который я хочу ссылаться только на бизнес-уровне.

моя путаница находится между уровнем бизнес-логики и уровнем проекта MVC (UI). классы моей модели просмотра находятся в папке Model внутри проекта MVC, а уровень бизнес-логики имеет ссылку на уровень доступа к данным, имеющий классы таблиц базы данных. поэтому моя модель представления не распознается на уровне бизнес-логики. если я хочу добавить проект MVC (где существует моя модель представления) ссылку на уровень бизнес-логики, это дает ошибку циклических зависимостей. Я много искал на форумах и в учебниках, но не нашел решения или не понял концепции.

мой уровень бизнес-логики и уровень доступа к данным - это библиотечный проект, а уровень пользовательского интерфейса - проект MVC

если какое-либо тело может объяснить на примере, отправив модель представления данных на уровень бизнес-логики и получив модель обратного представления от уровня бизнес-логики

Уровень доступа к данным

namespace DAL.Infrastructure.Contract
{

    public interface IBaseRepository<T> : IDisposable where T : class
    {
        IEnumerable<T> GetAll();
        IEnumerable<T> FindIEnumerableByExpression(Expression<Func<T, bool>> predicate);
        T FindFirstOrDefaultByExpression(Expression<Func<T, bool>> predicate);
        T GetById(object Id);
        T Insert(T entity);
        T Delete(T entity);
        void Update(T entity);
        void Save();
    }
}



namespace DAL.Infrastructure
{
    public class BaseRepository<T> : IBaseRepository<T> where T : class
    {
        public PMSEntities dbContext = null;
        public DbSet<T> dbSet = null;

        public BaseRepository()
        {
            this.dbContext = new PMSEntities();
            dbSet = dbContext.Set<T>();
        }

        public virtual IEnumerable<T> GetAll()
        {
            return dbSet.AsEnumerable<T>();
        }

        public T GetById(object id)
        {
            return this.dbSet.Find(id);
        }

        public IEnumerable<T> FindIEnumerableByExpression(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
        {
            IEnumerable<T> query = dbSet.Where(predicate).AsEnumerable();
            return query;
        }

        public T FindFirstOrDefaultByExpression(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
        {
            return this.dbSet.FirstOrDefault(predicate);
        }

        public virtual T Insert(T entity)
        {
            return dbSet.Add(entity);
        }

        public virtual T Delete(T entity)
        {
            return dbSet.Remove(entity);
        }

        public virtual void Update(T entity)
        {
            dbContext.Entry(entity).State = System.Data.Entity.EntityState.Modified;
        }

        public void Save()
        {
            dbContext.SaveChanges();
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    dbContext.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
    }
}

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

Пожалуйста, попробуйте прочитать этот ответ, он может вам помочь: stackoverflow.com/questions/14887871/…

Alaaeddine HFIDHI 09.04.2019 10:57
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
137
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

ViewModels не должны быть частью уровня бизнес-логики, поскольку они предназначены исключительно для представления. То, как вы организовали это сейчас, делает так, что бизнесу НУЖЕН пользовательский интерфейс/представление, которому нужен бизнес, чтобы начать работу, которому нужен пользовательский интерфейс/представление, чтобы начать работу (повторяю...)

UI/View может знать о бизнес-уровне, но не наоборот. Таким образом, "правильный" способ сделать это - сначала сопоставить информацию вашей базы данных с обычным объектом C#, который ваш уровень пользовательского интерфейса может запросить через бизнес-уровень. После этого уровень пользовательского интерфейса может выполнить свою работу, преобразовав его в класс, оптимизированный для отображения этой информации, ViewModel. Это не означает, что вы должны делать это внутри контроллера, вы можете добавить другие классы в свой проект пользовательского интерфейса/представления, которые позаботятся о логике.

Пользовательский интерфейс/представление может знать о бизнесе, бизнес может знать о доступе к данным, но не наоборот. Таким образом, вы не получите циклических зависимостей и запутанного кода.

Я надеюсь, что это имеет смысл для вас.

Очень хорошее объяснение. Но я бы никогда не получил доступ к уровню данных из уровня пользовательского интерфейса, это приводит к дублированию кода и нежелательным изменениям в сущностях. Всегда должен быть задействован бизнес-уровень для унифицированного доступа к данным и трансформации. Но это только мое мнение.

Rabban 09.04.2019 11:43

Полностью согласен, именно это я и хотел сказать! Добавил несколько дополнительных слов, чтобы прояснить это. Спасибо, что указали мне на это.

Roy 09.04.2019 11:45

Уважаемый @Roy, есть ли ссылка на учебник, где реализована эта концепция.

ALI 09.04.2019 12:26

Другие вопросы по теме