【发布时间】:2016-11-15 14:06:26
【问题描述】:
编辑 (02/03/2018): 由于 Entity Framework Core 2.1,EF Core 实现了事务、跨上下文事务、环境事务和事务范围,所以这个问题现在已经过时了。
这是有关 EF Core 中事务的官方文档:https://docs.microsoft.com/en-us/ef/core/saving/transactions。
如何在不同的方法中使用相同的事务?目标是在发生错误时提交或回滚所有修改。
我正在使用 Entity Framework Core 1.1.0-preview1-final 和 SQL Server 2014。
例如,我有一个实体框架数据库上下文:
public class ApplicationDatabaseContext : DbContext
{
public ApplicationDatabaseContext(DbContextOptions<ApplicationDatabaseContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TransactionLog1>(entity =>
{
entity.ToTable("TRANSACTION_LOG_1");
entity.Property(e => e.CreationDate)
.HasColumnType("datetime")
.HasDefaultValueSql("getdate()");
});
modelBuilder.Entity<TransactionLog2>(entity =>
{
entity.ToTable("TRANSACTION_LOG_2");
entity.Property(e => e.CreationDate)
.HasColumnType("datetime")
.HasDefaultValueSql("getdate()");
});
}
public virtual DbSet<TransactionLog1> TransactionLog1 { get; set; }
public virtual DbSet<TransactionLog2> TransactionLog2 { get; set; }
}
我有两个类来处理数据,它们都使用相同的上下文:
public interface IRepository1
{
void Create(Guid key);
}
public sealed class Repository1 : IRepository1
{
private readonly ApplicationDatabaseContext _dbContext;
public Repository1(ApplicationDatabaseContext dbcontext)
{
_dbContext = dbcontext;
}
public void Create(Guid key)
{
using (_dbContext.Database.BeginTransaction())
{
try
{
_dbContext.TransactionLog1.Add(new TransactionLog1 { Key = key });
_dbContext.SaveChanges();
_dbContext.Database.CommitTransaction();
}
catch (Exception)
{
throw;
}
}
}
}
public interface IRepository2
{
void Create(Guid key);
}
public sealed class Repository2 : IRepository2
{
private readonly ApplicationDatabaseContext _dbContext;
public Repository2(ApplicationDatabaseContext dbcontext)
{
_dbContext = dbcontext;
}
public void Create(Guid key)
{
using (_dbContext.Database.BeginTransaction())
{
try
{
_dbContext.TransactionLog2.Add(new TransactionLog2 { Key = key });
_dbContext.SaveChanges();
_dbContext.Database.CommitTransaction();
}
catch (Exception)
{
throw;
}
}
}
}
在我的业务逻辑中,我有一个服务,我想在我的第一个存储库上调用方法 void Create(Guid key),然后从我的第二个存储库中调用相同的方法并仅在以下情况下提交两者都没有错误发生(如果在第二个方法中发生任何错误,我想回滚在第一个方法中完成的提交)。
我该怎么做? Entity Framework Core 和事务的最佳实践是什么?
我尝试了几件事,像这样,但它从来没有用过(使用这种方法我有错误):
Warning 作为警告的错误异常 'RelationalEventId.AmbientTransactionWarning':环境事务 已被检测到。 Entity Framework Core 不支持环境 交易。
public sealed class Service3 : IService3
{
private readonly IRepository1 _repo1;
private readonly IRepository2 _repo2;
public Service3(IRepository1 repo1, IRepository2 repo2)
{
_repo1 = repo1;
_repo2 = repo2;
}
public void Create(Guid key)
{
using (TransactionScope scope = new TransactionScope())
{
try
{
_repo1.Create(key);
_repo2.Create(key);
scope.Complete();
}
catch (Exception)
{
throw;
}
}
}
}
我阅读了文档,尤其是此页面 (https://docs.microsoft.com/en-us/ef/core/saving/transactions),但我没有 Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade 上的方法 UseTransaction。 p>
【问题讨论】:
-
经过更多研究,我认为当前版本的 Entity Framework Core 不可能:github.com/dotnet/corefx/issues/12534。下个版本好像已经计划好了
标签: c# transactions entity-framework-core asp.net-core-1.0 sql-server-2014-express