1. 程式人生 > >數據訪問層及EntityFramework

數據訪問層及EntityFramework

定義 標識 comm first 工作 ret 延遲 dot obj

數據訪問層(Data Access Layer)負責與數據儲存設備打交道,為業務層提供數據服務(一般指增、刪、改、查)。一個好的數據訪問層可在不影響其他邏輯的情況下,替換數據訪問技術、數據據庫。

數據訪問層的常見模式與原則

  • 工作單元(Unit of Work)
    維護一系列操作的事務性(Transaction),一系列操作要麽都成功,如果有一個操作失敗,則事務回滾。這裏也主要用於對數據庫的操作。
    如果通過sql腳本直接訪問數據庫,可以直接用sql調用相應數據庫的事務。
    如果采用自己寫的ORM,則可定義一個IUnitOfWork接口,將增、刪、改的數據保存進集合,在Commit方法將object數據存儲數據庫,可通過TransactionScope
    實現事務使用方式連接。
    public interface IUnitOfWork
    {
        void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
        void RegisterNew(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
        void RegisterRemoved(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
        void Commit();
    }

如果利用第三方ORM庫,一般都提供Unit of work

  • 標識映射
    標識映射即通過唯一標識,將加載的數據存入緩存,方便下次訪問。
  • 延遲加載 表示需要時才去加載所需的資源。一般指需要時采取加載外鍵關聯的表。如在學生管理系統,每個學生都有自己的成績,在展示學生列表時不加載成績,只有進入某個學生詳細信息才加載。
  • 數據並發控制
    同時修改一份數據造成修改沖突,一般通過為數據添加一個version屬性表明版本。

    EntityFramework

    EntityFramework是微軟官方提供的ORM類庫,其采用Repository模型,功能強大,這裏簡單介紹下其數據訪問層特性的實現。

    工作單元(Unit of Work)

  1. 隱式事務
  using (var context = new MyStoreContext())
  {
    customer = new Customer { FirstName = request.FirstName, LastName = request.LastName };
    context.Customers.Add(customer);
    context.SaveChanges();
    return customer;
  }

其中context.SaveChanges()方法事務執行,其內部實現了事務。

  1. 顯示事務
using (var context = new BloggingContext())
{
    using (var transaction = context.Database.BeginTransaction())
    {
        try
        {
            context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
            context.SaveChanges();

            context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
            context.SaveChanges();

            var blogs = context.Blogs
                .OrderBy(b => b.Url)
                .ToList();

            transaction.Commit();
        }
        catch (Exception)
        {
            // TODO: Handle failure
        }
    }
}
  1. Cross-context transaction(跨庫的事務)
using (var context1 = new BloggingContext(connectionstring1))))
{
    using (var transaction = context1.Database.BeginTransaction())
    {
        try
        {
            context1.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
            context1.SaveChanges();

            using (var context2 = new BloggingContext(connectionstring2))
            {
                //context2 用context1的事務
                context2.Database.UseTransaction(transaction.GetDbTransaction());

                var blogs = context2.Blogs
                    .OrderBy(b => b.Url)
                    .ToList();
            }

            transaction.Commit();
        }
        catch (Exception)
        {
            // TODO: Handle failure
        }
 

延遲性加載

EntityFramework 默認為延遲加載,如果希望饑渴加載需要include

數據並發控制

為實體添加version屬性

   [Timestamp]
    public byte[] RowVersion { get; set; }

通過異常機制查詢保存的數據是否被修改或刪除,異常為DbUpdateConcurrencyException

數據訪問層及EntityFramework