After the release of .NET Framework 3.5 SP1 from Microsoft, more and more developers interested in ADO.NET Entity Framework and hope to use it in their applications’ data access layer. But the current version of Spring.NET data access part only supports primitive ADO.NET and NHibenate, they don’t know how to integrate EF into Spring.NET and get benefits from Spring.NET transaction management and strength AOP ability. Because I also encountered same problem and did not get result from Internet, today after the research, I wrote an example describes this.
在微軟發布 .NET Framework 3.5 SP1 之後,ADO.NET Framework 吸引了越來越多的開發人員和將它 用到了項目的數據訪問層中。但是,當前版本的 Spring.NET 只支持原始的 ADO.NET 和 NHibernate,大 家不知道該如何將 EF 和 Spring.NET 進行集成並從 Spring.NET 的事務管理和強壯的 AOP 中獲得好處 。我也遇到了相同的問題,在網上也沒有找到任何結果。今天在進行研究之後,我寫了一個關於這個的例 子。
The most efficient way of controlling transaction with EF is using System.Transactions.TransactionScope, so in the example we also use it.
在使用 EF 的時候,最有效的是使用 System.Transactions.TransactionScope 來控制事務,所以這 個例子也是使用的它。
First of all, I think that we need to understand the mechanism of how Spring.NET manages transaction. As we known, Spring.NET transaction control is base on its AOP, which means the transaction control codes are dynamically injected into methods configured with transaction need at runtime. The following codes illustrate the mechanism.
在開始之前,我想我們先需要理解 Spring.NET 管理事務的機制。如我們所知道的,Spring.NET 的事 物控制是基於它的 AOP 的,這意味著,事物控制代碼是在運行時被動態插入那些被配置為需要事物的方 法的。下面的代碼描繪了這個機制。
Our real code:
我們的代碼:
[Transaction]
static void DbOperation()
{
// Our data access code
}
AOP acted on code:
AOP 作用後的代碼:
[Transaction]
static void DbOperation()
{
TransactionScope ts = new TransactionScope();
try
{
// Our data access code
ts.Complete();
}
finally
{
ts.Dispose();
}
}
After the understanding base on the previous code, we know that all we only need to do is using AOP ability from Spring.NET to inject transaction code arround ourself code of method. Because EF code needs a System.Data.Objects.ObjectContext object to interact with underlying database, so we can provide a base class for our data access classes.
在理解了以上代碼之後,我們知道,所有我們需要做的就是利用 Spring.NET 的 AOP 能力將插入事務 代碼,用事務代碼“包裹”我們自己的方法的代碼。因為 EF 代碼需要一個 System.Data.Objects.ObjectContext 對象用於和底層數據庫進行交互,所以我們需要為我們的數據訪問 類提供一個基類。
Final code:
最後的代碼:
public class EFSupport<TObjectContext> : DaoSupport
where TObjectContext : ObjectContext
{
public TObjectContext Database { get; set; }
protected override void CheckDaoConfig()
{
if (this.Database == null) throw new ArgumentException("Database cannot be null.");
}
}
public interface IOrderDao
{
void AddOrder(Order order);
void AddOrderItems(IList<OrderItem> orderItems);
}
public class OrderDao : EFSupport<DemoEntities>, IOrderDao
{
[Transaction]
public void AddOrder(Order order)
{
this.Database.AddToOrderSet(order);
this.Database.SaveChanges();
}
[Transaction]
public void AddOrderItems(IList<OrderItem> orderItems)
{
foreach (var item in orderItems)
{
this.Database.AddToOrderItemSet(item);
}
this.Database.SaveChanges();
}
}
<objects xmlns="http://www.springframework.net">
<object id="EFTxSampleEntities" type="Demo.EFTxSample.EFTxSampleEntities">
<constructor-arg name="connectionString" value="metadata=res://*;provider=System.Data.SqlClient;provider connection string="Data Source=HOME-WZH-02;Initial Catalog=Demo;Integrated Security=True;MultipleActiveResultSets=True""/>
</object>
<object id="orderDao" type="Demo.EFTxSample.OrderDao">
<property name="Database" ref="EFTxSampleEntities"/>
</object>
<object id="transactionManager"
type="Spring.Data.Core.TxScopeTransactionManager, Spring.Data">
</object>
<object id="autoProxyCreator"
type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator, Spring.Aop"/>
<object id="transactionAdvisor"
type="Spring.Transaction.Interceptor.TransactionAttributeSourceAdvisor, Spring.Data">
<property name="TransactionInterceptor" ref="transactionInterceptor"/>
</object>
<object id="transactionInterceptor"
type="Spring.Transaction.Interceptor.TransactionInterceptor, Spring.Data">
<property name="TransactionManager" ref="transactionManager"/>
<property name="TransactionAttributeSource" ref="attributeTransactionAttributeSource"/>
</object>
<object id="attributeTransactionAttributeSource"
type="Spring.Transaction.Interceptor.AttributesTransactionAttributeSource, Spring.Data"/>
</objects>
The attachment is a complete example.
附件裡是一個完整的例子。
本文配套源碼