2009-09-20 58 views
5

我一直在浏览教程(特别是使用Linq-To-Entities的教程),并且我理解基本概念,但有些东西给我提出了一些问题。我的ASP.NET MVC应用程序结构是否正确?

本教程通常只涉及简单的模型和形式,只使用基本的创建,更新和删除语句。我的情况稍微复杂一点,我不确定我是否正确地做这件事,因为当处理六个数据库对象的关系时,教程停止提供帮助。

对于POST方法,执行CRUD操作

entities.AddToTableSet(myClass); 
entities.SaveChanges(); 

不会做我想做的,因为完全实现的类不获取发布到控制器方法的常用方式。我可能会发布单个字段,表单集合或多个DTO对象,然后调用服务或存储库上的方法来获取我从表单帖子收到的信息以及它需要查询或创建的信息,然后从所有这些东西,创建我可以保存的数据库对象。

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Add(int id, [Bind(Exclude = "Id")] ClassA classA, 
         [Bind(Exclude = "Id")]ClassB classB) 
{ 
    // Validation occurs here 

    if(!ModelState.IsValid) 
     return View(); 

    try 
    { 
     _someRepositoryOrService.Add(id, classA, classB); 
     return RedirectToAction("Index", new { id = id }); 
    } 
    catch(Exception ex) 
    { 
     // Logging and exception handling occurs here 
    } 
} 


public void Add(int id, ClassA classA, ClassB classB) 
{ 
    EntityA eA = new EntityA 
    { 
     // Set a bunch of properties using the two classes and 
     // whatever queries are needed 
    }; 

    EntityB eB = new EntityB 
    { 
     // Set a bunch of properties using the two classes and 
     // whatever queries are needed 
    }; 

    _entity.AddToEntityASet(eA); 
    _entity.AddToEntityBSet(eB); 
    _entity.SaveChanges(); 
} 

我正确地处理这个问题还是我混蛋框架?我从来没有直接使用实体对象,每当我查询一个我在DTO中放置需要的信息并将其视为基于我的视图时。创作也一样。这是允许的,还是我避免使用实体直接违背使用框架的目的?

编辑:我也担心这种方法,因为它需要空构造做正确,因为此错误信息的LINQ查询:

只有参数构造函数和 初始化在LINQ的支持,以 实体。

这不是什么大不了的事情,因为我很少需要构造函数中的逻辑int,但是这是没有构造函数和公共属性的问题吗?

+1

Linq to Entities使用的objectcontext使用反射来创建数据映射中的对象,因此很重要,并且要求所有实体都有一个无参数的构造函数,以便可以初始化,如果您希望能够序列化您的类型也需要一个公共的构造函数 – dmportella 2009-09-28 12:04:30

回答

4

_someRepositoryOrService.Add(id,classA,classB);

我会说你把你的存储库与表示层连接起来。这不应该。您的存储库只能与实体一起使用。接下来,注意你的Add方法

公共无效添加(INT ID,ClassA的CLASSA,ClassB的CLASSB)的关注(SoC)的

断裂分离如何。它执行两个任务:

  1. 地图视图数据到实体
  2. 保存到存储库

显然,第一步应该在表示层来完成。考虑使用模型粘合剂。它还可以帮助您解决施工人员的问题,因为您的模型活页夹可以了解施工要求。

请查看Jimmy Bogard(ASP.NET MVC In Action的作者之一)关于ViewModels的优秀post。这可能会帮助您自动映射。它还提出了一种颠倒的技术 - 让你的控制器与实体协作,而不是ViewModels!自定义操作过滤器和模型绑定器是消除例程的关键,这些例程并不属于控制器,而是视图和控制器之间的基础架构细节。例如,here的我如何自动化实体回顾。 Here是我如何看到控制器应该做什么。

这里的目标是让控制器满意地管理业务逻辑,把所有不属于您业务的技术细节放在一边。你在这个问题中讨论的技术约束,你让他们泄漏到你的代码中。但是您可以使用MVC工具将它们移动到基础架构级别。

更新:不,仓库不应该处理表单数据,这就是我的意思是“与演示文稿结合”。是的,存储库位于控制器中,但它们不适用于表单数据。您可以(并非您应该)使用“存储库数据”(即实体)进行表单处理,而这正是大多数示例所做的工作。 NerdDinner - 但不是其他方式。这是因为一般的经验法则 - 较高层可以与较低层耦合(表现与存储库和实体耦合),但从不低层应该耦合到较高层(实体取决于存储库,存储库取决于表单模型等) )。

第一步应该在存储库中完成,这是正确的 - 除了从ClassX到EntityX的映射不属于该步骤。它正在映射关注点 - 一个基础设施。例如,请参阅this有关映射的问题,但通常如果您有两层(UI和存储库),则不应关心映射 - 映射器服务/帮助器应该。除了Jimmy的博客,您还可以阅读ASP.NET MVC In Action,或者简单地看一下他们如何与传递给控制器​​构造函数的IEntityMapper接口进行映射(请注意,这是Jimmy Bogard的AutoMapper更为人工且工作量较少的方法)。

还有一件事。阅读关于领域驱动设计,寻找文章,向他们学习,但你不必去关注一切。这些是准则,而不是严格的解决方案看看你的项目是否可以处理这个问题,看看你是否可以处理这个问题,等等。尝试应用这些技术是因为它们通常是优秀且经过批准的开发方式,但不要盲目采取 - 最好是在学习的过程中比应用不理解的东西更好。

+0

对于耦合存储库,我不确定你的意思,在控制器中拥有一个存储库似乎是大多数教程所做的。至于表示层中的第一步,不应该在存储库中完成吗?我认为存储库的目的是担心处理表单数据到数据库转换? – Brandon 2009-10-01 06:31:54

+0

也感谢你的例子和建议。我没有时间去实际做出改变,但这是一个很好的方向。 – Brandon 2009-10-01 06:33:16

+0

查看更新。我建议慢慢重构,例如首先做_realEntityRepository.Add(EntityMapper.From(classA)); (或classA.MapToEntity()),然后涉及自定义ModelBinder(这是一个很大的话题),然后添加IoC容器(另一个大话题)等等。 – queen3 2009-10-01 10:10:36

4

我会说使用DTO和使用您自己的数据访问方法和业务层包装实体框架是一个好方法。您最终可能会编写大量代码,但它比假装实体框架生成的代码是您的业务层更好。

这些问题并不一定以任何方式绑定到ASP.NET MVC。 ASP.NET MVC基本上没有提供关于如何进行模型/数据访问的指导,ASP.NET MVC的大多数示例和教程都不是有生产价值的模型实现,但实际上只是最小的样本。

看起来你正处在正确的轨道上,继续前行。最终,您最常使用实体框架作为代码生成器,它不会生成非常有用的代码,因此您可能需要查看其他代码生成器或更符合您需求的工具或框架。

+0

我真的只使用实体框架来尝试新的东西。我用于使用nHibernate。对于我应该使用的更好的发生器或框架,你有什么建议吗? – Brandon 2009-09-20 19:32:49

+0

我不知道有什么东西可以满足您的需求。其中一些是商业的,一些是免费的。没有特别的顺序:T4模板,CodeSmith,LLBLGen Pro。 – 2009-09-21 07:15:06

+1

这主要是一个非常好的答案(+1),但我不同意他使用实体框架作为代码生成器。更重要的是他正在使用实体框架将他的数据库映射到对象空间。即使您从未实际实现实体类型,这也很重要;当您将它们投影到其他类型时,仍然在您的LINQ to Entities查询中使用映射实体。 – 2009-09-21 13:38:24

相关问题