我目前正在使用EF6和业务规则的服务模式。我需要交易。不幸的是,我对EF如何管理交易没有深入的了解。请看下面的代码:
public class Service1
{
private DbContext context;
private string connectionString = "yada, yada, yada";
public Service1()
{
context = new DbContext(connectionString); //DbContext is IRL a
context from an EF-dbfirst project, this is only for illustration
}
public void SaveStuff(object stuff)
{
var transaction = context.Database.BeginTransaction();
try
{
var s2 = new Service2();
context.[DbEntity].Add(stuff);
s2.SaveOtherStuff("stuff");
context.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
}
}
}
public class Service2
{
private DbContext context;
private string connectionString = "yada, yada, yada";
public Service2()
{
context = new DbContext(connectionString);
}
public void SaveOtherStuff(object stuff)
{
context.[DbEntity].Add(stuff);
}
}
使用Service1上下文对象创建事务。交易是否会跟随Service2或Service2使用上下文对象而不知道正在进行的事务?我是否需要以某种方式将拥有事务的上下文对象传递给Service2(构造函数)?
答案 0 :(得分:0)
答案是否定的,这似乎都是一个糟糕的设计。
一些注释:您不应该真正创建并保留DbContexts
或Transactions
,Disposed
中的using
都应该Transaction
理想的陈述
但是,我相信你可以对多个DBContexts
使用相同的using (TransactionScope scope = new TransactionScope())
{
using (myContext context = new myContext())
{
Test t = new Test()
t.Name="TEST";
context.AddToTests(t);
context.SaveChanges();
}
using (myContext context = new myContext())
{
Demo d = context.Demos.First(s => s.Name == "Demo1");
context.DeleteObject(d);
context.SaveChanges();
}
scope.Complete();
// also make sure you add error checking and rollback
}
,但我认为这可能依赖于SqlServer版本,如果数据库存在于同一个SqlServer中,那么就不要引用我就是那个"
DBContext
最后,在不同的Service调用上使用相同的上下文似乎是错误的,您不需要缓存EF
,DBContext
这项工作非常适合幕后工作
<强>更新强>
我刚注意到您为每项服务创建了一个新的using
。无论如何,对DbContext
和Transaction
使用PARAMETERS
[Forms]![Reports Window]![cmb_ar] Long,
[Forms]![Reports Window]![ar_frm_dt] DateTime,
[Forms]![Reports Window]![ar_to_dt] DateTime;
SELECT
ITEM, [Transaction Date], ID, Reciept, Issued, Returns, Remarks, Manual
FROM
<snip>
语句或冒被同事诋毁的风险:)
答案 1 :(得分:0)
我不明白为什么你需要实例化两个dbcontext,但是如果你通过服务共享相同的dbcontext,你不需要使用显式事务(.SaveChanges()自己创建一个sql事务)然后将dbContext传递给构造函数中的Service2。
如果你想使用两个不同的dbContext,你只能共享事务和第一个dbContext的连接,那么:
public void SaveStuff(object stuff)
{
using(var transaction = context.Database.BeginTransaction())
{
try
{
var s2 = new Service2(transaction, context.Database.Connection);
context.[DbEntity].Add(stuff);
s2.SaveOtherStuff("stuff");
context.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
}
}
}
public class Service2
{
private DbContext context;
public Service2(DbContextTransaction transaction, DbConnection connection)
{
context = new DbContext(connection, false);
context.Database.UseTransaction(transaction);
}
public void SaveOtherStuff(object stuff)
{
context.[DbEntity].Add(stuff);
}
}