Я бы согласился с комментарием Hightechrider в отношении использования DTO, однако у вас есть действительный вопрос в отношении бизнес-структур.
Одним из возможных решений (я использую что-то в этом духе в разрабатываемом проекте) является использование DTO, которые доступны только для чтения (по крайней мере, с точки зрения уровня представления. Ваши операции запрос / получение будут возвращать только DTO , это даст вам возможность ленивой загрузки.
Вы можете настроить свой бизнес-уровень так, чтобы он возвращал редактируемый объект, который переносит DTO, когда объект / сущность обновляется / создается. Ваш редактируемый объект может применять любые бизнес-правила, а затем, когда он был сохранен / передан на бизнес-уровень, DTO, который он обернул (с обновленными значениями), может быть передан на уровень данных.
public class Editable
{
//.......initialize this, other properties/methods....
public bool CanEdit<TRet>(Expression<Func<Dto, TRet>> property)
{
//do something to determine can edit
return true;
}
public bool Update<TRet>(Expression<Func<Dto, TRet>> property, TRet updatedValue)
{
if (CanEdit(property))
{
//set the value on the property of the DTO (somehow)
return true;
}
return false;
}
public Dto ValueOf { get; private set;}
}
Это дает вам возможность принудительно установить, может ли пользователь получать редактируемые объекты из бизнес-уровня, а также разрешить принудительное применение бизнес-объекта, если у пользователя есть разрешение на редактирование определенных свойств объекта. Распространенная проблема, с которой я сталкиваюсь в домене, в котором я работаю, заключается в том, что некоторые пользователи могут редактировать все свойства, а другие - нет, а любой может просматривать значения свойств. Кроме того, уровень представления получает возможность определять, что следует показывать пользователю как доступное для редактирования, как предписано и применяется бизнес-уровнем.
Другая мысль, которая у меня возникла, заключается в том, что ваш бизнес-уровень не может предоставлять IQueryable или принимать стандартные выражения в качестве аргументов, передаваемых на уровень данных. Например, у меня есть запрос на создание страницы что-то вроде этого:
public class PageData
{
public int PageNum;
public int TotalNumberPages;
public IEnumerable<Dto> DataSet;
}
public class BL
{
public PageData GetPagedData(int pageNum, int itemsPerPage, Expression<Func<Dto, bool>> whereClause)
{
var dataCt = dataContext.Dtos.Where(whereClause).Count();
var dataSet = dataContext.Dtos.Where(whereClause).Skip(pageNum * itemsPerPage).Take(itemsPerPage);
var ret = new PageData
{
//init this
};
return ret;
}
}