在微软发布 .NET Framework 3.5 SP1 之后,ADO.NET Framework 吸引了越来越多的开发人员和将它用到了项目的数据访问层中。但是,当前版本的 Spring.NET 只支持原始的 ADO.NET 和 NHibernate,大家不知道该如何将 EF 和 Spring.NET 进行集成并从 Spring.NET 的事务管理和强壮的 AOP 中获得好处。我也遇到了相同的问题,在网上也没有找到任何结果。今天在进行研究之后,我写了一个关于这个的例子。
在使用 EF 的时候,最有效的是使用 System.Transactions.TransactionScope 来控制事务,所以这个例子也是使用的它。
在开始之前,我想我们先需要理解 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();
}
}
在理解了以上代码之后,我们知道,所有我们需要做的就是利用 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>
附件里是一个完整的例子。