C# efn层体系结构
导言 我们需要构建一个n层应用程序,因为我们希望在多个平台上共享我们的BL,并且只编写一次DAL。我已经在这个问题上做了一些研究 正如在Davide Piras的帖子中所读到的:每个VS解决方案必须至少有4层。到目前为止还不错 他还表示,DAL项目是唯一一个被允许知道EF正在使用的项目 问题1: 我假设“接口”项目的接口是我的EF实体的1对1表示,我的说法正确吗?此外,这些接口应作为不同层之间的类型使用 问题2: 建议在WPF或WinForms项目中,DbContext的生存期应为每个WebApps请求一个上下文,每个表单一个上下文。那么,如何在不向GUI层添加“System.Data.Entity”的情况下实现这一点呢C# efn层体系结构,c#,entity-framework,architecture,n-tier-architecture,C#,Entity Framework,Architecture,N Tier Architecture,导言 我们需要构建一个n层应用程序,因为我们希望在多个平台上共享我们的BL,并且只编写一次DAL。我已经在这个问题上做了一些研究 正如在Davide Piras的帖子中所读到的:每个VS解决方案必须至少有4层。到目前为止还不错 他还表示,DAL项目是唯一一个被允许知道EF正在使用的项目 问题1: 我假设“接口”项目的接口是我的EF实体的1对1表示,我的说法正确吗?此外,这些接口应作为不同层之间的类型使用 问题2: 建议在WPF或WinForms项目中,DbContext的生存期应为每个WebAp
提前通知 首先不要通过多个平台共享您的DAL。共享使用DAL的BL。只要您的BL代表您的应用程序需求的解决方案,您就不需要公开您的DAL,请不要公开。此外,暴露DAL的缺点是向黑客暴露更多漏洞,直接访问DAL为BL中的业务逻辑、控制和验证提供了btpass机制 答案1: 可能,但不需要。考虑到SOA,我建议使用DTO。它们要么是实体,要么是由多个和/或部分实体组成的更复杂的复合类。如果您使用实体,这将使您能够更灵活地通过BL提供信息(您可以通过一个方法调用一次发送数据的多个部分),并对第三方用户隐藏您的实体(也是DB结构),从而提供更好的安全感 答案2: 同样,考虑到SOA,不要根据用户界面构造BL/服务方法。BL(顾名思义)根据“如何完成工作”而不是“用户如何在屏幕上完成工作”提供数据。如果您试图从GUI管理数据,也将开始违反N层体系结构不要使用DAL之外的任何数据特殊类和/或方法。这将是分层的真正用途
关于。您需要将
工作单元
和存储库
模式与依赖项注入框架(如or)结合使用
基本上,您需要做的是创建接口:
public interface IUnitOfWork
{
void SaveChanges();
}
public interface IRepository<TItem>
{
TItem GetByKey<TKey>();
IQueryable<TItem> Query();
}
public void RegisterDependencies(Container container)
{
// Container is a Structure Map container.
container.ForRequestedType<IUnitOfWork>()
.CacheBy(InstanceScope.HttpContext)
.TheDefaultConcreteType<DbContext>();
}
有关如何配置实例的作用域,请参见
现在,所有这些代码就绪后,需要执行某些数据操作的业务层
类的每个类都将如下所示:
public class SomeService
{
public SomeService(IRepository<SomeItem> repository, IUnitOfWork unitOfWork)
{
this.repository = repository;
this.unitOfWork = unitOfWork;
}
public void MarkItemCompleted(int itemId)
{
var item = repository.GetByKey(itemId);
if(item != null)
{
item.Completed = true;
unitOfWork.SaveChanges();
}
}
}
公共类服务
{
公共服务(IRepository存储库、IUnitOfWork unitOfWork)
{
this.repository=存储库;
this.unitOfWork=unitOfWork;
}
public void markitempleted(int itemId)
{
var item=repository.GetByKey(itemId);
如果(项!=null)
{
item.Completed=true;
unitOfWork.SaveChanges();
}
}
}
现在,隐藏工厂后面的服务创建:
public class ServiceFactory
{
private readonly Container container;// = initialize the container
public TService CreateService<TService>()
{
return container.GetInstance<TService>();
}
}
公共类服务工厂
{
私有只读容器容器;//=初始化容器
公共TService CreateService()
{
返回container.GetInstance();
}
}
在GUI层中,只调用通过
ServiceFactory
创建的服务类的方法;如果您的GUI是ASP.NET MVC项目,则不需要创建ServiceFactory
类-您可以从DefaultControllerFactory
派生并重写GetControllerInstance
方法。请参阅示例。Thnx有关否决票,如果我遗漏了什么,请发表评论。。我已经投入了一些精力和时间来问这些问题。谢谢你的快速回答!很抱歉,我想说的不是像向其他GUI公开DAL那样共享DAL,而是只编写一次!我的错。如果我帮了忙,我很高兴。是的,你帮了忙;)。我会在几个小时内标记为答案,我仍在等待更多的意见,我认为当一个问题仍然没有答案时,人们会更加渴望。没问题。我答应帮忙,不是为了名誉。祝你有一个愉快的一天。是的,它必须在BL中完成。任何UI都只会看到你的BL(作为API),并且只会与此层通信。如何转换数据取决于您使用的语言和/或您的开发首选项。在我当前的项目中,我们只使用ADO.NET,所以我通过存储过程从数据库中获取数据,并从DAL返回接口。在BL中,我从接口创建模型(我的UI仅限于ASP.NET MVC!!!)并返回它。但是我更倾向于使用ORM工具(比如像DAL这样的实体框架)并编写LinQ查询来获得[this]()结构.Thnx,以获得清晰的响应!这很有帮助。我已经遇到了寄存和UOW模式。我认为回购协议的实施应该在DAL中,对吗?再次使用Thnx。@MarkRijsmus,是的,它应该在数据访问中。