• 功能与接口定义


    功能与接口定义

    数据访问层的设计我研究了很长时间,关于接口的定义,好几次都推翻重来。

    园子看到过很多easyui+MVC+EF的文章,在早期,我的设计也类似。

    但是后来为了增强它,想加点功能通用的功能进去,就耗费了非常多的时间。

    这是一个怎么样的DAL?

    也许你已经见过许多实用EF的架构了,它是一套基于领域模型架构中的DAL。

    大致结构如图中,DAL就是最下面的那一层。

    它的主要功能也体现在图中了:增删改服务、查询、事务管理、并发,另外事务中包括工作单元,查询中包括延迟加载。

    我们希望底层的数据库操作对其他层来说是透明的。

    例如BLL将感受不到ORM工具的存在,他也不需要知道我们操作的数据库是Oracle,还是MSSQLServer。

     所以需要给DAL抽象出一个统一的接口,供其他层来操作,而底层我们可以分别使用各种ORM工具,或者原生SQL去实现。

    看到图中,会发现设计好DAL统一的上下文是重点,因为它将会提供给其他层统一的接口,接口的定义是一个难点。

    一个比较好的设计是底层实现依赖与高层抽象,而DAL不能去依赖EFDAL/NHDAL,这里使用IOC工具就能轻松实现。

    关于上下文的类图:

    IDataContext就是DAL的上下文,而它需要被EF的上下文(context)/NH的上下文(session)分别实现,而原生的SQL只能通过实现它的接口来构成所谓的上下文。

    其中BaseDataContext就是实现了一些通用的功能,比如事务管理、工作单元、唯一标识。

    你会发现许多人都在BLL直接使用ORM的上下文,那是因为DAL并没有提供统一的上下文接口,只是提供了一个统一的仓储接口(IRepository,比如IUserRepository)。

    所以BLL只能使用仓储接口,而不能使用上下文中事务管理和工作单元,为了的条件查询要么让仓储提供更多的查询方法,DAL中ORM特定的上下文贯穿所有层。

    在上一篇BLL调用DAL的演示中,主要为了说明业务层事务控制方法,这次贴一个更加具体的例子。

    复制代码
            [Test]
            public void QueryTest()
            {
                IDataContext context = DataContextFactory.GetDataContext();
                Query query = new Query();
                //条件
                query.AddCriteria("Name", "%yan", CriteriaOperator.Like);
                query.AddCriteria("IsDelete",true,CriteriaOperator.NotEq);
                //排序
                query.AddOrderClause("CreateTime", false);
                query.AddOrderClause(new OrderClause() { ascending = true, PropertyName = "ID" });
                //根据条件查询
                IList<User> users= context.GetByCriteria<User>(query);
                foreach (User user in users)
                {
                    Console.WriteLine("id:{0}	name:{1}", user.ID, user.Name);
                    Console.WriteLine("department:{0}",user.Department.Name);//延迟加载
                }
            }
    复制代码

            id:11 name:yan
            department:mydept
            id:10 name:13yan
            department:mydept

    上面的例子已经可以看到,统一的上下文能够支持条件查询和延迟加载。可以看出我使用的是那种ORM吗?

    分页

    复制代码
            [Test]
            public void PageListTest()
            {
                Query query = new Query();
                query.AddCriteria("IsDelete", true, CriteriaOperator.NotEq);
                query.AddOrderClause("ID", true);
                IDataContext context = DataContextFactory.GetDataContext();
                IList<User> users = context.GetByCriteria<User>(query,0, 10);
                int count = context.GetCount<User>(query);
                foreach (User user in users)
                {
                    Console.WriteLine("id:{0}	name:{1}", user.ID, user.Name);
                }
                Console.WriteLine("sum:{0}",count);
            }
    复制代码

    id:1 name:lucy
    id:3 name:Lily
    id:9 name:nddd
    id:10 name:13yan
    id:11 name:yan
    id:41 name:adama3
    sum:6

    非工作单元

     在非工作单元的事务中,Add之后立即写入了数据库,可以看到user1已经写入数据库,并且持久化了。

    工作单元

    在工作单元的事务中,只要没有Commit(),新增对象的任务只是被暂存起来,到提交时一并执行。可以发现Add之后并没有写入数据库和持久化。

    小结:中午时间真是短暂,时间关系就先写到这里吧,有兴趣再接下去分析。

     
     
    分类: 架构设计
  • 相关阅读:
    css盒子模型、垂直外边距合并
    mov指令和 add以及sub 指令的区别
    第一章 基础知识
    字符串文档的去重
    python 之 字符串的常用方法
    python格式化输出之format用法
    python 格式化输出之%号
    c++11可变参数模板的使用1
    深入浅出 c++11 std::async
    std::thread 概述
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3201561.html
Copyright © 2020-2023  润新知