問題描述
存儲庫模式問題 (Repository Pattern Question)
I have two repository classes below, MoneyTransferRepository class is used by other classes in my project. I have designed it this way ‑ is it right? If not, what is the best way?
Thanks
public interface IMoneyTransferRepository
{
void UpdateBalance();
}
public interface IOrderRepository
{
void Checkout();
void SaveOrder();
}
public class MoneyTransferRepository : IMoneyTransferRepository
{
DBDataContext DB;
public MoneyTransferRepository(IDbConnection connection)
{
DB = new DBDataContext(connection);
}
public void UpdateBalance()
{
//do something DB.Table1.Update
}
}
public class OrderRepository : IOrderRepository,IMoneyTransferRepository
{
DBDataContext DB;
IMoneyTransferRepository moneyTransferRepository;
public OrderRepository()
{
DB = new DBDataContext();
moneyTransferRepository = new MoneyTransferRepository(DB.Connection);
}
public void Checkout()
{
TransactionOptions transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;
using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
try
{
UpdateBalance();
SaveOrder();
transactionScope.Complete();
}
catch
{
}
}
}
public void UpdateBalance()
{
moneyTransferRepository.UpdateBalance();
}
public void SaveOrder()
{
//do something DB.SaveOrder.Update ......
// DB.Updatestock .....
}
}
‑‑‑‑‑
參考解法
方法 1:
This is most definitely not the correct usage of the repository pattern. I find the easiest way to think about the repository is to imagine every Order in your system is available in a big collection (the repository). That said you probably want to add a way to query for specific objects from the repository (either via a Query pattern or direct method calls).
In our system we would have a service layer method called Checkout that would look like this...
public void Checkout(int customerId) { if(CustomerHasOpenOrder(customerId) == false) { // do something depending on your standards. For us we'd // throw an exception } Order orderToCheckout = m_OrderRepository.FindOpenOrderForCustomer(customerId); orderToCheckout.Checkout(); m_OrderRepository.Save(orderToCheckout); }
In our system we don't actually use int's for identifying Orders but you get the idea...
方法 2:
Don't do transaction management in Repository. Thats why you get confused.
More info is here: Transactions in the Repository Pattern
(by tobias、Shane Courtrille、ercu)