我想知道在实体框架中使用转换的最佳方法是什么。
说我有三个存储库:
Repo1(ObjectContext context)
Repo2(ObjectContext context)
Repo3(ObjectContext context)
以及一个包含三个存储库的服务对象:
Service(Repo1 repo1,Repo2 repo2, Repo3 repo3)
Serive.CreateNewObject <- calls repo1, repo2, repo3 to do stuff.
因此,当我创建服务时,我先创建三个存储库并将其传递下来,每个存储库都会获取一个对象上下文,因此我的代码看起来像这样:
MyObjectContext context = new MyObjectContext();
Repo1 repo = new Repo1(context);
// etc
现在我有一个控制器类,负责调用我的应用程序的不同服务和组件,显示正确的表单等。现在我想要做的是将一个控制器方法中发生的一切包装在一个交易,以便如果出现问题我可以回滚。
控制器接受一些不同的Service对象,但对对象上下文一无所知。
我的问题是:
很抱歉,如果有点难以理解......
答案 0 :(得分:3)
为什么你的控制器不知道ObjectContext?
这是我想说的。签出 - http://msdn.microsoft.com/en-us/magazine/dd882510.aspx - 这里的命令是提交/回滚UnitOfWork(ObjectContext)的内容。
如果您不想让控制器知道完全关于EF(优秀设计),那么您希望将ObjectContext抽象为类似于上述链接中的方法的接口。
答案 1 :(得分:3)
如何使用自定义TransactionScope,即在所有服务都已提交时提交的事务?
public class TransactionScope : Scope<IDbTransaction>
{
public TransactionScope()
{
InitialiseScope(ConnectionScope.CurrentKey);
}
protected override IDbTransaction CreateItem()
{
return ConnectionScope.Current.BeginTransaction();
}
public void Commit()
{
if (CurrentScopeItem.UserCount == 1)
{
TransactionScope.Current.Commit();
}
}
}
因此,只有在UserCount为1时才会提交事务,这意味着最后一项服务已提交。
范围类是(羞耻我们不能做附件......):
public abstract class Scope<T> : IDisposable
where T : IDisposable
{
private bool disposed = false;
[ThreadStatic]
private static Stack<ScopeItem<T>> stack = null;
public static T Current
{
get { return stack.Peek().Item; }
}
internal static string CurrentKey
{
get { return stack.Peek().Key; }
}
protected internal ScopeItem<T> CurrentScopeItem
{
get { return stack.Peek(); }
}
protected void InitialiseScope(string key)
{
if (stack == null)
{
stack = new Stack<ScopeItem<T>>();
}
// Only create a new item on the stack if this
// is different to the current ambient item
if (stack.Count == 0 || stack.Peek().Key != key)
{
stack.Push(new ScopeItem<T>(1, CreateItem(), key));
}
else
{
stack.Peek().UserCount++;
}
}
protected abstract T CreateItem();
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// If there are no users for the current item
// in the stack, pop it
if (stack.Peek().UserCount == 1)
{
stack.Pop().Item.Dispose();
}
else
{
stack.Peek().UserCount--;
}
}
// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
}
disposed = true;
}
}
public class ScopeItem<T> where T : IDisposable
{
private int userCount;
private T item;
private string key;
public ScopeItem(int userCount, T item, string key)
{
this.userCount = userCount;
this.item = item;
this.key = key;
}
public int UserCount
{
get { return this.userCount; }
set { this.userCount = value; }
}
public T Item
{
get { return this.item; }
set { this.item = value; }
}
public string Key
{
get { return this.key; }
set { this.key = value; }
}
}
public class ConnectionScope : Scope<IDbConnection>
{
private readonly string connectionString = "";
private readonly string providerName = "";
public ConnectionScope(string connectionString, string providerName)
{
this.connectionString = connectionString;
this.providerName = providerName;
InitialiseScope(string.Format("{0}:{1}", connectionString, providerName));
}
public ConnectionScope(IConnectionDetailsProvider connectionDetails)
: this(connectionDetails.ConnectionString, connectionDetails.ConnectionProvider)
{
}
protected override IDbConnection CreateItem()
{
IDbConnection connection = DbProviderFactories.GetFactory(providerName).CreateConnection();
connection.ConnectionString = connectionString;
connection.Open();
return connection;
}
}
答案 2 :(得分:1)
将操作包裹在TransactionScope。
中答案 3 :(得分:0)
您可能希望实现Workflow Foundation使用的事务模型。它基本上有一个所有“组件”实现的接口。在每次成功完成主要工作之后,主机在每个上面调用“commit”方法。如果一个失败,它会调用“回滚”方法。