摘要 :在上一篇文章中,我们比较了ADO.net和其他Data Provider,以提高应用程序数据访问层的性能 。下面我们的主题将是采用一些常用的设计模式来使用ORM(通常是N-hibernate和EF)建立数据访问层---UnitOfWork,Repository设计模式和SOA。
其实ORM不应该属于这个系列的范围,因为它不会帮助改善我们的第一个应用程序的性能。ORM并不适合快速数据交易系统(要求有很好的实时性)。
我们经常会遇到一个数据库事务,在不同的数据表上有操作需要,UnitOfWork结合Repository模式是通用的设计方法,例如:
Unit of work-- Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.
A Unit of Work keeps track of everything you do during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database as a result of your work.
---Martin Flower
从Martin Flower的说明我们可以理解UnitOfWork的主要用途:
(1)管理事务 。
(2)实现数据的插入,删除和更新。
(3)防止重复更新。通过对保持对象的跟踪,防止多次提交数据库操作,提高性能。
Repository
Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects
Repository模式主要用于实现业务层和数据访问层的隔离。这样做的好处是客户端代码(此处指业务层的service代码)不依赖于具体数据存储的实现。并且Repository只需要暴露必须的数据访问给Service层。
下面我们来看利用这两个模式针对我们的需求做的一个简单的实现(使用Entity Framework中ObjectContext 来实现简单的UnitOfWork的功能)
这些类之间的关系比较简单,
核心代码
public interface IUnitOfWork
{
void Save();
}
public interface ICustomerRepository
{
Customer GetCustomerByName(string name);
Customer AddCustomer(Customer customer);
}
public interface IOrderRepository
{
Order GetOrderById(int id);
Order AddOrder(Order order);
}
public class CustomerRepository : ICustomerRepository
{
private OrderEntities _context;
public CustomerRepository(IUnitOfWork unitOfWork)
{
_context = unitOfWork as OrderEntities;
}
public Customer GetCustomerByName(string name)
{
return _context.Customers.Where(c => c.Name == name).FirstOrDefault();
}
public Customer AddCustomer(Customer customer)
{
_context.Customers.AddObject(customer);
return customer;
}
}
public class OrderRepository : IOrderRepository
{
private OrderEntities _context;
public OrderRepository(IUnitOfWork unitOfWork)
{
_context = unitOfWork as OrderEntities;
}
public Order GetOrderById(int id)
{
return _context.Orders.Where(c => c.Id == id).FirstOrDefault();
}
public Order AddOrder(Order order)
{
_context.Orders.AddObject(order);
return order;
}
}
public class CustomerInfo
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
public class OrderInfo
{
public int Id { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
public CustomerInfo CustomerInfo { get; set; }
}
public static class CustomerTranslator
{
public static Customer Translate(CustomerInfo customerInfo)
{
return new Customer { Id = customerInfo.Id, Name = customerInfo.Name, Address = customerInfo.Address };
}
}
public static class OrderTranslator
{
public static Order Translate(OrderInfo orderInfo)
{
return new Order { Id = orderInfo.Id, Quantity = orderInfo.Quantity, Price = orderInfo.Price };
}
}
public class OrderService
{
public void CreateNewOrder(OrderInfo orderInfo)
{
IUnitOfWork unitOfWork = new OrderEntities();
CustomerRepository customerRepository = new CustomerRepository(unitOfWork);
Customer customer = customerRepository.GetCustomerByName(orderInfo.CustomerInfo.Name);
if (customer == null)
{
customer = customerRepository.AddCustomer(CustomerTranslator.Translate(orderInfo.CustomerInfo));
}
OrderRepository orderRepository = new OrderRepository(unitOfWork);
Order order = OrderTranslator.Translate(orderInfo);
order.Customer = customer;
orderRepository.AddOrder(order);
unitOfWork.Save();
}
}
class Program
{
static void Main(string[] args)
{
OrderService orderService = new OrderService();
CustomerInfo c1 = new CustomerInfo();
c1.Name = "Demo Customer";
c1.Address = "Demo Address";
OrderInfo orderInfo = new OrderInfo();
orderInfo.CustomerInfo = c1;
orderInfo.Price = 200;
orderInfo.Quantity = 5;
orderService.CreateNewOrder(orderInfo);
Console.Write("new order saved.");
}
}
测试结果:
结论
目前我们这个对UnitOfWork和Repository模式的实现存在一些问题。
接下来,我们将针对上面的问题推出优化后的设计和实现。使得整个架构具有更好的扩展性。
---P.S. 运行程序,请
(1)运行数据库脚本script.sql
(2)改变app.config文件中的连接字符串 。