【发布时间】:2015-11-08 18:44:55
【问题描述】:
我目前正在重构一个 ASP.NET MVC 项目以使用 onion arcitecture,因为它似乎适合未来发展的需要。
我已经设置了我认为需要使用的层,我的解决方案现在看起来像这样:
所以,基本上据我所知,ClientName.Coreproject 根本不应该有任何对其他项目的引用。 ClientName.Infrastructure 应该有对ClientName.Core 的引用。 ClientName.Core 上的 Interfaces 文件夹定义了 ClientName.Infrastructure 项目中的服务,并且我的 DbContext 和域实体是分开的,因此只有实体在核心项目中。
我头疼的地方是,ClientName.Infrastructure 项目不应该将域实体返回给调用它的任何客户端。这将在核心项目和任何“违反”洋葱原则的 UI 之间创建一个引用。正如我所读到的,解决这个问题的一种方法是让基础设施服务返回 DTO。但是,如果我从 PersonService 类返回 PersonDto,则 PersonDto 对象需要被 ClientName.Core 项目知道,因为这是接口所在的位置。
所以问题是:我应该将用于 UI/客户端的 DTO/ViewModel/其他模型放在哪里?我是否创建一个单独的类库来保存这些模型并让 UI、基础设施和核心项目都引用它?
非常感谢任何帮助/提示,因为我对此有点困惑 ;-)
提前致谢。
编辑
基于 Euphorics 的回答,我在这里编写示例代码只是为了检查我是否做对了,也许还有一些后续问题。
所以基本上,在我的ClientName.Core 层中,我的实体包含业务逻辑,即Person 和Firm 实体可能如下所示:
(Exists in ClientName.Core/Entities)
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public Firm Firm { get; set; }
}
(Exists in ClientName.Core/Entities)
Public class Firm
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<Person> Employees { get; set; }
public IEnumerable<Person> GetEmployeesByName(string name)
{
return Employees.Where(x => x.Name.Equals(name));
}
public void AddEmployee(Person employee)
{
Employees.Add(employee);
}
public void CreateFirm(Firm firm)
{
// what should happen here? Using entity framework, I have no reference to the DbContext here...
}
}
(Exists in ClientName.Infrastructure/Services)
public class FirmService : IFirmService
{
private readonly IDbContext _context;
public FirmService(IDbContext context)
{
_context = context;
}
public Firm GetById(int firmId)
{
return _context.Firms.Find(firmId);
}
// So basically, this should not call any domain business logic?
public void CreateFirm(CreateFirmFormViewModel formViewModel)
{
Firm firm = new Firm()
{
Name = formViewModel.Name;
}
_context.Firms.Add(firm);
_context.SaveChanges();
}
public IEnumerable<Person> GetEmployeesByName(int firmId, string name)
{
Firm firm = _context.Firms.Find(firmId);
return firm.GetEmployeesByName(name);
}
}
我是否正确,每个读取查询都应该直接在实体上定义(可能作为实体扩展,因为我使用的是实体框架)并且任何创建/更新/删除都只会发生在基础设施层的服务中?
读取(即IEnumerable<Person> GetEmployeesByName(int firmId, string name) 方法)方法是否也应该在FirmService 接口/类上?
再次感谢:-)
【问题讨论】:
标签: c# asp.net-mvc entity-framework onion-architecture