2011-03-22 61 views
0

在我的ASP.NET MVC应用程序中,我需要实现数据的持久性。我已经选择了Entity Framework,因为它能够根据实体模型创建类,数据库表和查询​​,这样我就不必手工编写SQL表创建或Linq到SQL查询。所以简单是我的目标在ASP.NET MVC应用程序中使用EntityFramework的持久性

我的方法是创建模型,并创建一个自定义的HttpModule,并在每个请求处调用该对象,并在上下文中调用SaveChanges()。这让我的生活变得非常艰难 - 实体框架一直在抛出非常奇怪的例外。有时它有效 - 没有例外,但有时它没有。首先,我试图逐个解决问题,但是当我得到另一个问题时,我意识到我的一般方法可能是错误的。

那么这是在ASP.NET MVC应用程序中实现持久性的一般实践吗?每次更改后,我只需拨打saveChanges?这不是没有效率吗?我不知道如何用Services patter做到这一点(服务与实体协同工作,所以我必须传递上下文实例给他们,这样他们才能保存更改,如果他们做了一些)。

一些学习材料或教程的链接也受到赞赏。


注意:这个问题要求编程练习。我会问那些会认为它含糊不清的人,记住它仍然在解决我非常特别的问题,正确的技术会在投票结束之前为我节省很多技术问题。

+1

通过阅读你的描述我有,你正在使用的上下文的单一共享实例不好的感觉,只是调用'SaveChanges'上http模块中的结束请求期间的实例。 – 2011-03-22 22:48:35

+0

@Ladislav Mrnka你不好的感觉是对的,但现在我正在重建这个使用存储库模式。只需要弄清楚如何正确使用该模式。 – drasto 2011-03-23 04:40:22

+1

在这里你有描述为什么你目前的解决方案没有工作:http://stackoverflow.com/questions/3653009/entity-framework-and-connection-pooling/3653392#3653392 – 2011-03-23 05:46:28

回答

1

你只需要确保SaveChanges得到您的请求完成之前调用。在控制器的底部,动作是理想的地方。我的控制器动作通常是这样的:

public ActionResult SomeAction(...) 
{ 
    _repository.DoSomething(); 
    ... 
    _repository.DoSomethingElse(); 
    ... 
    _repository.SaveChanges(); 
    return View(...); 
} 

这额外的好处是,如果一个异常被抛出,然后调用SaveChanges将不会被调用。您可以处理操作中的异常或Controller.OnException

+0

如何将该存储库保存更改到全局操作过滤器中,以便自动调用它,而无需在每个操作处手动编写它?会有什么缺点吗? – drasto 2011-03-22 19:15:32

+1

问题在于如果(在我的示例中)'DoSomething()'完成并向存储库添加了有效更改。但是,然后'DoSomethingElse()'失败,所以在这一点上,我不想再保存任何更改?如果您在所有请求后自动调用SaveChanges,则可能导致数据损坏。基本上上述模式是一个穷人的交易。在真实的交易中真正运行所有这些东西会更好。 – 2011-03-22 19:18:57

+0

@Matt格里尔没有一些方法来检查在动作过滤执行期间是否有异常?这将解决你正在解决的问题,它将仍然是'自动'... – drasto 2011-03-22 19:29:39

2

与调用一个存储过程的次数(关于需要建立的连接数量)没有多少差别。

名义上,您将对对象集进行所有更改,然后使用SaveChanges提交所有这些更改。

所以不是这样:

mySet.Objects.Add(someObject); 
mySet.SaveChanges(); 
mySet.OtherObjects.Add(someOtherObject); 
mySet.SaveChanges(); 

你只需要做:

mySet.Objects.Add(someObject); 
mySet.OtherObjects.Add(someOtherObject); 
mySet.SaveChanges(); 
// Commits Both Changes 
1

通常你的数据访问被一个实现了repsitory模式的对象包装。然后调用存储库上的Save()方法。

喜欢的东西

var customer = customerRepository.Get(id); 
customer.FirstName = firstName; 
customer.LastName = lastName; 
customerRepository.SaveChanges(); 

该存储库然后由服务层提供视图模型对象或DTO的

是不是那个小低效的包裹?

不要过早地优化。当您遇到性能问题时,请分析性能,找出原因并优化。重复。

更新

阿库封装数据的访问,通常是一个单独的实体。服务层包装业务逻辑并可通过多个存储库访问多个实体。它通常涉及'苗条'模型或DTO的。

一个例子可能是这样获得的发票清单为客户

public Customer GetCustomerWithInvoices(int id) { 

    var customer = customerRepository.Get(id); 
    var invoiceList = invoiceRepository.GetAllInvoicesFor(id); 

    return new Customer { 
    Customer = customer, 
    Invoices = invoiceList 
    }; 

} 
+0

你能给我一个关于服务层如何包装存储库层的例子吗? – drasto 2011-03-22 19:12:22

+1

@drasto我为您添加了更新。 – 2011-03-22 19:31:59

相关问题