Я новичок в 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);
}
}
}
я хочу использовать этот класс выше на уровне бизнес-логики, а не непосредственно в контроллере. вот мое замешательство, как написать слой бизнес-логики и использовать автоматическое сопоставление в слое бизнес-логики с ошибкой циклических зависимостей
ViewModels не должны быть частью уровня бизнес-логики, поскольку они предназначены исключительно для представления. То, как вы организовали это сейчас, делает так, что бизнесу НУЖЕН пользовательский интерфейс/представление, которому нужен бизнес, чтобы начать работу, которому нужен пользовательский интерфейс/представление, чтобы начать работу (повторяю...)
UI/View может знать о бизнес-уровне, но не наоборот. Таким образом, "правильный" способ сделать это - сначала сопоставить информацию вашей базы данных с обычным объектом C#, который ваш уровень пользовательского интерфейса может запросить через бизнес-уровень. После этого уровень пользовательского интерфейса может выполнить свою работу, преобразовав его в класс, оптимизированный для отображения этой информации, ViewModel. Это не означает, что вы должны делать это внутри контроллера, вы можете добавить другие классы в свой проект пользовательского интерфейса/представления, которые позаботятся о логике.
Пользовательский интерфейс/представление может знать о бизнесе, бизнес может знать о доступе к данным, но не наоборот. Таким образом, вы не получите циклических зависимостей и запутанного кода.
Я надеюсь, что это имеет смысл для вас.
Очень хорошее объяснение. Но я бы никогда не получил доступ к уровню данных из уровня пользовательского интерфейса, это приводит к дублированию кода и нежелательным изменениям в сущностях. Всегда должен быть задействован бизнес-уровень для унифицированного доступа к данным и трансформации. Но это только мое мнение.
Полностью согласен, именно это я и хотел сказать! Добавил несколько дополнительных слов, чтобы прояснить это. Спасибо, что указали мне на это.
Уважаемый @Roy, есть ли ссылка на учебник, где реализована эта концепция.
Пожалуйста, попробуйте прочитать этот ответ, он может вам помочь: stackoverflow.com/questions/14887871/…