热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ioc初步理解(一)简单实用autofac搭建mvc三层+ioc(codeFirst)

1】首先搭好框架1.1】搭建ui层1.2】创建其他内库文件整个项目基本部分搭建完毕之后如下2】使用nuget引用文件先在每一个项目中引入ef然后再UI层引

1】首先搭好框架

 1.1】搭建ui层

  1.2】创建其他内库文件

整个项目基本部分搭建完毕之后如下

2】使用nuget引用文件

先在每一个项目中引入ef

然后再UI层引入以下两个文件autofac和Autofac.Mvc5

 

 

3】因为本demo实用codefirst,所以先去model层完善

  3.1】创建几个model 

   创建一个  User.cs。里面放几个属性 id、name、pwd。

  3.2】创建DBContext.cs这个文件的作用是自动生成数据库 内容如下

 

  3.3】创建DbModelContextFactory.cs。此处作用是:获取当前EF上下文的唯一实例;  内容如下

4】创建DAL层内容【需要使用nuget引入ef文件  和model文件。dal层还需要引入idal】

  4.1】首先完善IDAL(接口)内容

    4.1.1】首先完成基础部分,创建IBaseDAL.cs 在里面添加增删改查这四个基本操作(注意IDAL中全是接口不是类,所以新建的时候注意吧class改成interface)代码如下
 public interface IBaseDAL where TEntity : class 
    { 

        #region 1.0 增

        void Add(TEntity model);

        #endregion

        #region 2.0 删

        void Delete(TEntity model, bool isAddedDbContext);



        #endregion

        #region 3.0 改

        
        void Edit(TEntity model, string[] propertyNames);


        #endregion

        #region 4.0 查

        #region 4.0.1 根据条件查询

        
        List QueryWhere(Expressionbool>> where);

        #endregion
        #endregion

        #region 5.0 统一保存

        /// 
        /// 统一将EF容器对象中的所有代理类生成相应的sql语句发给db服务器执行
        /// 
        /// 
        int SaveChanges();

        #endregion

    }
View Code

 

    4.1.2】根据自己在model中创建的模型,在此处也一一对应的创建其dal层接口。所在这里创建一个IUser_DAL.cs  内容如下:

因为所创建的model只有一个user,所以IDAL层到此结束。

  4.2】接下来创建DAL部分内容

   4.2.1】首先创建DbContextFactory.cs  =>   //获取当前EF上下文的唯一实例 代码如下

    public class DbContextFactory
    {       //获取当前EF上下文的唯一实例
        public static DbContext GetCurrentThreadInstance()
        {
            DbContext obj = CallContext.GetData(typeof(DbContextFactory).FullName) as DbContext;
            if (obj == null)
            {
                obj = new DBContext();
                CallContext.SetData(typeof(DbContextFactory).FullName, obj);
            }
            return obj;
        }
    }
View Code

 

    4.2.2】首先创建BaseDAL.cs 在里面写入具体的增删该查操作,代码如下:
public class BaseDAL : IBaseDAL where TEntity : class
    {//1.0  实例化EF上下文 
        DbContext db = DbContextFactory.GetCurrentThreadInstance();

        //2.0 定义DbSet 对象
        public DbSet _dbset;

        //3.0 在构造函数的初始化_dbset
        public BaseDAL()
        {
            _dbset = db.Set();
        }


        #region 1.0 增

        public virtual void Add(TEntity model)
        {
            //1.0 参数合法性验证
            if (model == null)
            {
                throw new Exception("BaseRepository泛型类中,新增操作的实体不能为空");
            }


            //2.0 进行新增操作 
            _dbset.Add(model);
        }


        #endregion

        #region 2.0 删

        public virtual void Delete(TEntity model, bool isAddedDbContext)
        {
            //1.0 参数合法性验证
            if (model == null)
            {
                throw new Exception("BaseRepository泛型类中,删除操作的实体不能为空");
            }

            //2.0 进行删除逻辑处理
            if (!isAddedDbContext)
            {
                _dbset.Attach(model);
            }

            _dbset.Remove(model);
        }


        #endregion

        #region 3.0 改

        /// 
        /// 编辑,约定model 是一个自定义的实体,没有追加到EF容器中的
        /// 
        /// 
        public virtual void Edit(TEntity model, string[] propertyNames)
        {
            //0.0 关闭EF的实体属性合法性检查
            db.Configuration.ValidateOnSaveEnabled= false;

            //1.0 参数合法性验证
            if (model == null)
            {
                throw new Exception("BaseRepository泛型类中,编辑操作的实体不能为空");
            }

            if (propertyNames == null || propertyNames.Length == 0)
            {
                throw new Exception("BaseRepository泛型类中,编辑操作的属性数组必须至少有一个值");
            }

            //2.0 将model追加到EF容器中的
            DbEntityEntry entry = db.Entry(model);
            entry.State = EntityState.Unchanged;

            foreach (var item in propertyNames)
            {
                entry.Property(item).IsModified = true;
            }
        }

        #endregion

        #region 4.0 查



        /// 
        /// 带条件查询
        /// 
        /// 
        /// 
        public virtual List QueryWhere(Expressionbool>> where)
        {
            return _dbset.Where(where).ToList();
        }
        #endregion


        #region 5.0 统一保存

        /// 
        /// 统一将EF容器对象中的所有代理类生成相应的sql语句发给db服务器执行
        /// 
        /// 
        public virtual int SaveChanges()
        {
            try
            {
                return db.SaveChanges();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion


    }
View Code
   4.2.3】创建 User_DAL.cs文件,内容如下

 

5】创建BLL的内容【需要使用nuget引入ef文件   和导入model层。dal层文件,bll层还需要引入ibll层】

  5.1】先创建IBLL(接口)层的内容

    5.1.1】创建IBaseBLL.cs。代码如下
public interface IBaseBLL where TEntity : class
    {
        #region 1.0 增

        void Add(TEntity model);

        #endregion

        #region 2.0 删

        void Delete(TEntity model, bool isAddedDbContext);



        #endregion

        #region 3.0 改

        /// 
        /// 编辑,约定model 是一个自定义的实体,没有追加到EF容器中的
        /// 
        /// 
        void Edit(TEntity model, string[] propertyNames);


        #endregion

        #region 4.0 查

      

        /// 
        /// 带条件查询
        /// 
        /// 
        /// 
        List QueryWhere(Expressionbool>> where);

        

      

        #endregion
         

        #region 5.0 统一保存

        /// 
        /// 统一将EF容器对象中的所有代理类生成相应的sql语句发给db服务器执行
        /// 
        /// 
        int SaveChanges();

        #endregion

       
    }
View Code
   5.1.2】根据model层的模型创建ibll层接口。所在这里创建一个IUser_BLL.cs  内容如下:

 

  5.2】完善BLL层内容

    5.2.1】创建BaseBLL.cs,代码如下
  public   class BaseBLL : IBaseBLL where TEntity : class
    {
        protected IBaseDAL dal = null;
        #region 1.0 增

        public virtual void Add(TEntity model)
        {
            dal.Add(model);
        }


        #endregion

        #region 2.0 删

        public virtual void Delete(TEntity model, bool isAddedDbContext)
        {
            dal.Delete(model, isAddedDbContext);
        }


        #endregion

        #region 3.0 改

        /// 
        /// 编辑,约定model 是一个自定义的实体,没有追加到EF容器中的
        /// 
        /// 
        public virtual void Edit(TEntity model, string[] propertyNames)
        {
            dal.Edit(model, propertyNames);
        }

        #endregion

        #region 4.0 查

        /// 
        /// 带条件查询
        /// 
        /// 
        /// 
        public virtual List QueryWhere(Expressionbool>> where)
        {
            return dal.QueryWhere(where);
        }
          

        #endregion 

        #region 5.0 统一保存

        /// 
        /// 统一将EF容器对象中的所有代理类生成相应的sql语句发给db服务器执行
        /// 
        /// 
        public virtual int SaveChanges()
        {
            return dal.SaveChanges();
        }

        #endregion



    }
View Code
   5.2.2】根据model层的模型创建bll层文件。所在这里创建一个User_BLL.cs  代码如下:
   public class User_BLL : BaseBLL, IUser_BLL
    {
        IUser_DAL dalSer;
        public User_BLL(IUser_DAL dalSer)
        {
            base.dal = dalSer;
            this.dalSer = dalSer;
        }
    }
View Code

至此,基础部分建立完毕,接下来建立ui层内容

6】建立UI层内容【需要引入bll文件和dal文件  也就是6.1中图中的两个文件,否则autofac报错,找到不到文件】

  6.1】首先在App_Start文件夹下建AutoFacConfig.cs文件

 

代码:

    public class AutoFacConfig
    { /// 
      /// 负责调用autofac框架实现业务逻辑层和数据仓储层程序集中的类型对象的创建
      /// 负责创建MVC控制器类的对象(调用控制器中的有参构造函数),接管DefaultControllerFactory的工作
      /// 
        public static void Register()
        {
            //实例化一个autofac的创建容器
            var builder = new ContainerBuilder();
            //告诉Autofac框架,将来要创建的控制器类存放在哪个程序集 (IOCtsX.UI)
            Assembly cOntrollerAss= Assembly.Load("IOCtsX.UI");
            builder.RegisterControllers(controllerAss);

            //告诉autofac框架注册数据仓储层所在程序集中的所有类的对象实例
            Assembly respAss = Assembly.Load("IOCtsX.IDAL");
            //创建respAss中的所有类的instance以此类的实现接口存储
            builder.RegisterTypes(respAss.GetTypes()).AsImplementedInterfaces();

            //告诉autofac框架注册业务逻辑层所在程序集中的所有类的对象实例
            Assembly serpAss = Assembly.Load("IOCtsX.BLL");
            //创建serAss中的所有类的instance以此类的实现接口存储
            builder.RegisterTypes(serpAss.GetTypes()).AsImplementedInterfaces();

            //创建一个Autofac的容器
            var cOntainer= builder.Build();
            //将MVC的控制器对象实例 交由autofac来创建
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


        }
    }
View Code

  6.2】然后再Global.asax中进行配置 如下:

  6.3】创建一个公共层,使用nuget引入mvc和ef。添加文件IOCDI.cs 根据创建mode层中模型的数量写入内容:(写公共层主要考虑项目的扩展性,如果本项目中需要些api或者其他ui层时候,避免代码重复)【需要用nuget引入mvc、ef 和ibll层(注意此处mvc版本必须和ui层中mvc版本相同)】

 

7】最后创建一个控制器添加数据看看,

 7.1】先配置Web.config

 

 7.2】创建一个测试控制器(由于是codefirs所以不需要先创建数据库)

最后查看数据库

 

 

【最后附上关于autofac的几点疑惑】

1因为在ui层的App_Start下的AutoFacConfig.cs需要,所以ui层必须引用bll层和dal层,这和三层的理念有些差异。因为三层中ui层并不需要引入dal层。

【结尾说明,关于了解autofac花掉的时间说长也长说短也短。原本以为在博客园、csdn上面找一找就能马上得到一个可以运行的demo,但是很多博主都是按照自己的理解去写,在博文中或多或少会掉一些内容,这些内容对于博主和一些大牛来说是可以忽略不计的,因此博文只需要核心代码就可以,但是对于我这种萌新来说简直是灾难级别的,因为跟着博主敲打代码过程中时长因为缺点什么而无法运行,自己也不知道错误在哪。因此不得不敲到一半立马换下一个。导致效率低下。所以在写这个博文的过程中。我尽量将每一个细节全部罗列出来,以免像我这样的小白看不懂。照着这个流程讲代码敲出来并且运行时没什么大问题的。因为我每敲完一处就写一点。最后将代码运行完毕,才敢上传。如果各位看官觉得有什么问题可以在下方留言】

【如果需要代码可以去此下载,当然懒人也需要一点付出(csdn 3积分)。博主希望大家尽量多动手,多理解。不要像我之前一样只需要demo从不看文章导致后来吃了许多亏】

 


推荐阅读
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 标题: ... [详细]
  • 摘要: 在测试数据中,生成中文姓名是一个常见的需求。本文介绍了使用C#编写的随机生成中文姓名的方法,并分享了相关代码。作者欢迎读者提出意见和建议。 ... [详细]
  • 本文讨论了Kotlin中扩展函数的一些惯用用法以及其合理性。作者认为在某些情况下,定义扩展函数没有意义,但官方的编码约定支持这种方式。文章还介绍了在类之外定义扩展函数的具体用法,并讨论了避免使用扩展函数的边缘情况。作者提出了对于扩展函数的合理性的质疑,并给出了自己的反驳。最后,文章强调了在编写Kotlin代码时可以自由地使用扩展函数的重要性。 ... [详细]
author-avatar
lippor
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有