我们正在构建一个使用ADO.NET的遗留框架的应用程序。该框架管理自己与DB的连接,以调用其代码API。
对于任何自定义表和自定义表,我们使用的是Entity Framework,因此会与DB建立单独的连接。
应用程序和数据库将托管在Azure上。
我们想要做的是将对遗留框架和实体框架的调用都包含在同一个事务中。
我们的理解是这是一个分布式事务,但Azure中不提供此功能。
有没有办法让它在Azure环境中运行?
e.g。
using (var transaction = new TransactionScope())
{
using (var db = new EntityFrameworkDBEntities())
{
Order order = db.Orders.FirstOrDefault();
order.Name = "1";
db.SaveChanges();
}
using (var legacyAPI = new LegacyAPI())
{
Customer customer = legacyAPI.GetCustomers.FirstOrDefault();
customer.Name = "Charles";
legacyAPI.SaveCustomer(customer);
}
transaction.Complete();
}
答案 0 :(得分:1)
AFAIK您需要为事务使用相同的连接,因为SQL Azure不支持分布式事务。如果您在同一事务中使用多个连接,即使所有连接都连接到同一个数据库,ADO.NET也会升级到分布式事务。
答案 1 :(得分:0)
正如Shaun Xu所说,你只需要使用一个连接。如果您能够更改LegacyAPI以将开放连接和事务作为输入,那么使用EF6和edmx的方式如下:
var workspace = new MetadataWorkspace(new[] { "res://*/" }, new[] { Assembly.GetExecutingAssembly() });
using (var connection = new SqlConnection("Normal ADO connection string with MultipleActiveResultSets=True"))
{
using (var entityConnection = new EntityConnection(workspace, connection, false))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
using (var db = new EntityFrameworkDBEntities(entityConnection))
{
db.Database.UseTransaction(transaction);
// Do stuff with db
db.SaveChanges();
}
// Do ADO stuff on LegacyAPI using the connection and transaction objects
transaction.Commit();
}
}
}
要在dbcontext上获取额外的构造函数,请创建此部分类,其中false表示您手动打开和关闭连接。
partial class EntityFrameworkDBEntities
{
public EntityFrameworkDBEntities(DbConnection connection) : base(connection, false) { }
}
作为奖励,你现在只需要配置中的一个连接字符串,它不包括通常附带的所有无用的EF垃圾(metadata = res:// * / blabla)。
如果您拥有一个包含多个模式且每个模式都有一个edmx的数据库,那么这也有效。请注意,虽然EntityConnections是相同的,但每个dbcontext都需要一个。