【发布时间】:2018-01-15 23:38:06
【问题描述】:
如果有人能告诉我这一点,非常感谢!!!
抱歉,我看到了很多例子,但没有任何解决 MVC 模式的例子。
我的困境是 MVC 控制器 的实现,它可以处理多个请求和 Db 操作,但在操作员完成必要的流程之前永远不会提交任何内容。
例如,添加一条新的父记录并返回记录信息,并带有生成的 Id PrimaryKey。现在操作员可以通过传递必要的 ForiegnKey 来添加子记录。其中一些子记录可能有自己的子记录等。操作员必须在提交任何内容之前完成整个过程。
除非我完全关闭,否则我无法弄清楚这一点。我遇到了这些:
How to make a transaction in asp.net-core 2.0?
Alternative to TransactionScope of System.Transaction assembly in .net core framework
据我了解,System.Transactions 目前在 .Net Core 2.0.x 中可用。正如 3568202 中指出的那样:
https://docs.microsoft.com/en-us/dotnet/api/system.transactions.transactionscope?view=netcore-2.0
https://docs.microsoft.com/en-us/dotnet/framework/data/transactions/managing-concurrency-with-dependenttransaction 其中有一个我玩过的 WorkerThread 示例。
但该示例并未准确显示 Transactions.Current 的来源。这是我在控制器中遇到障碍的地方。
我无法从 MyDbContext.Database.BeginTransaction() 派生的 IDbContextTransaction 中找出转换;和 System.Transactions 的东西。
因为使用 IDbContextTransaction 创建的事务没有 .DependentClone()。
我错过了什么,一个接口?我不能把它放在一起......
然后我遇到了这个,看起来更简单一点:
与TransactionScope无关,第一行好像是救命:
“您还可以跨多个上下文实例共享事务。”
尝试在 Controller 中实现示例后,我不断感到恐惧:
“InvalidOperationException:指定的事务不是 与当前连接相关联。仅关联交易 可以使用当前连接。”
另外,最重要的是,在我所有的细读中,它似乎表明这并不多,如果使用注入的上下文可以实现这一点???!!!咦,什么,为什么?
如何使用正确的“使用”模式???
我正在使用 .Net Core 2.0.5 和 VS 2017 15.5.3
顺便说一句——我在这里没有使用存储库,但如果解决方案需要存储库,我会全力以赴。
这是我正在查看的基本设置
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{ }
public DbSet<Source> Sources { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<DwsFileInfo> DwsFileInfo { get; set; }
}
然后在Startup.ConfigureServices
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyConnection")));
然后是控制器:
public class MyController : Controller
{
private MyDbContext MyDbContext { get; set; }
private static IDbContextTransaction RootTransaction { get; set; }
//private DependentTransaction DependentTransaction { get; set; }
//private TransactionScope ScopedTransaction { get; set; }
public CommentsController(MyDbContext context)
{
MyDbContext = context;
if (RootTransaction == null)
{
RootTransaction = MyDbContext.Database.BeginTransaction();
}
else
{
MyDbContext.Database.UseTransaction(RootTransaction.GetDbTransaction());
}
}
/// <summary>
/// Not sure I really need this?!?
/// </summary>
~CommentsController()
{
if (RootTransaction != null && RootTransaction.GetDbTransaction() != null)
{
RootTransaction.Rollback();
}
RootTransaction.Dispose();
MyDbContext.Dispose();
}
public IActionResult Add(object recordinfo)
{
// DB operations
}
public IActionResult Add2(object recordinfo)
{
// DB operations
}
public IActionResult Edit(object recordinfo)
{
// Db Operations
}
/// <summary>
/// something here to manage, instead of in the constructor
/// or relying on the destructor??
/// </summary>
private void ManageTransaction()
{
//commit
//rollback
//dispose
}
}
我已经使用以下方法将一些特定于应用程序的信息注入到上下文中:
app.Use(next => context =>
{
string path = context.Request.Path;
//modify context accordingly per path
return next(context);
});
但无法准确定义“相应修改”的含义......现在我发现自己受 StackOverflow 的摆布...... 非常感谢大家的时间和考虑。非常感谢!!!
【问题讨论】:
-
抱歉,没有时间阅读所有内容,但要预先提供一个:不要使用静态字段,它不是线程安全的,您可能会遇到异常或不受欢迎的行为当多个请求同时发生时。您应该使用依赖注入(作用域或瞬态)
-
Transaction 是一个在整个(dugh)事务期间应该是活动的对象。当您发送响应时,您的控制器可能会与您的对象一起被处置,因此一种选择是将它们存储在静态服务器端集合中。问题是您还需要保持与数据库的整个连接,因为事务已绑定到它(这就是您收到该错误的原因)。为什么不重构其背后的逻辑并一次发送所有数据,而不是打开一个事务并逐项进行呢?
标签: asp.net-core .net-core asp.net-core-mvc relational-database entity-framework-core