zoukankan      html  css  js  c++  java
  • 事务的考虑

    事务的考虑

    写博文不容易,坚持写更不容易,写得快更加不容易。

    如果要写,必定是自己肚子里有货;坚持写,是学习能力的体现;又要工作又要持续学习,不写得快怎么能行呢。

    原本想把我的数据访问层也一起公开的,但是有朋友劝我不要发布。

    他告诉我:网上发布的多数是贴贴Demo,框架只有在实战中才有存在价值,发布出来一般也没人有那个耐心去看,早就沉没在信息的海洋里了。

    但我还是想把业务层都写完了。

    事务管理应该放在哪一层做

    事务的开始与提交应该放在哪里呢?业务逻辑层还是数据访问层?

    我以为,数据访问层需要,业务逻辑层也需要。

    数据访问层的仓储(Repository)做细粒度的事务,业务逻辑层做相对较粗的事务。

    那么具体如何实现呢?

    Repository中得事务,下面分别是3个版本的事务,原生SQL,NHibernate,Entity Framework,我之所以写3个版本,是想证明数据访问层随时可以切换,而业务层绝不能受制于它,无论拼接SQL还是HQL,都不是一个很好的习惯。

    复制代码
        public class UserRepository : BaseRepository,IUserRepository
        {
            public void SaveUser(User user)
            {
                //ADO.NET事务开始
                //省略执行SQL语句的操作……
                //ADO.NET事务提交
            }
        }
    复制代码
    复制代码
            public void SaveUser(User user)
            {
                ITransaction tran = Session.BeginTransaction();
                Session.Save(user);
                tran.Commit();
                tran.Dispose();
            }
    复制代码
    复制代码
            public void SaveUser(User user)
            {
                using (TransactionScope tx = new TransactionScope())
                {
                    context.AddObject("User",user);
                    tx.Complete();
                    context.AcceptAllChanges();
                }
            }
    复制代码


    业务层的事务,这里引入了System.Transactions命名空间,userRep.SaveUser(user2);这段就是刚才看到的,包含了一个事务的仓储,

    执行tx.Complete();才会走完这个事务,如果在using中出现了异常,那么所有事务都将回滚。其实是一个嵌套事务。

    复制代码
            [Test]
            public void TranTest()
            {
                IDataContext context = DataContextFactory.GetDataContext();
                Department dept = context.GetByID<Department>(1);
                User user1 = new User() { LoginName = "adama1", Name = "adama1", Password = "123123", Department = dept };
                User user2 = new User() { LoginName = "adama2", Name = "adama2", Password = "123123", Department = dept };
                IUserRepository userRep = RepostoryFactory.GetFor<User>() as IUserRepository;
                using (TransactionScope tx = new TransactionScope())
                {
                    context.Add(user1);
                    userRep.SaveUser(user2);
                    tx.Complete();
                }
            }
    复制代码

    上面的context不是EF的上下文,是DAL封装起来的上下文,可以给NHibernate和EF切换的统一接口。

    无论如何,架构设计者都不能让业务逻辑层感觉到ORM工具的存在,如果无法做到,那么定义了IRepository接口就成了摆设。

    在实际使用中,上面的例子完全可以加入上一篇提到的验证业务规则,它可以应付更加复杂的逻辑的。

    结尾:这几篇博文真的非常偏重于领域驱动,但有许多公司甚至连ORM是什么都不知道,用EF的公司只能说明技术总监很潮。

    下一次试着用一些简单传统的设计,也就不需要这么多的前置技能,设计更加随意。

    本篇开始出现许多绝对性的词语(无论,绝对,肯定),通常绝对性的话语都是错的,因为世事无绝对。

    但我还是那句话“写技术博文已经很理性了,为什么不能多加入一些感性的元素”。

    不知道还有没有机会写下去,心里有个声音:英语已经等不急了,快去看它吧。

     
     
    分类: 架构设计
  • 相关阅读:
    linux top详解
    软件人才必须具备的素质
    合格程序员每天每周每月每年应该做的事
    正则匹配任意字符(包括换行)
    软件测试方案
    LInux进程间的通信方式有哪儿些?
    三网融合
    php路径问题
    xp 安装SATA AHCI驱动
    进程与线程的区别
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3196866.html
Copyright © 2011-2022 走看看