• 数据访问层及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

  • 相关阅读:
    WebApi 2:属性路由 [Route()],attribute routing
    WebApi:路由和Action选择
    1024 科学计数法(20 分)
    1023 组个最小数(20 分)
    1022 D进制的A+B(20 分)
    1021 个位数统计(15 分)
    1020 月饼(25 分)
    1019 数字黑洞(20 分)
    1018 锤子剪刀布(20 分)
    1017 A除以B(20 分)
  • 原文地址:https://www.cnblogs.com/LoveTomato/p/9408868.html
Copyright © 2020-2023  润新知