前进中的蜗牛

番茄大叔

水滴穿石,非一日之功;没有量变,何来质变。

数据访问层及EntityFramework

数据访问层(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()方法事务执行,其内部实现了事务。
2. 显示事务

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

posted @ 2018-08-02 18:15  LoveTomato  阅读(260)  评论(0编辑  收藏  举报