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.
附件里是一个完整的例子。
Download example code(下载例子代码)