Fork me on GitHub

李可

导航

ASP.NET MVC系列 框架搭建(二)之仓储层的优化

大神勿喷,小神默默学。

会了就是不值一提的东西,不会就是绝对的高大上。

最后上传源码。希望能给读者带来一些新的认识及知识。

还没上过头条。。各位大神,请点支持一下小弟。

陆续更新。更新到你会为止!!

我不是话唠,我只把重点点出来,细枝末节的不懂的可以留言探讨。这个系列的最后,我会再统一的把大家的问题,列在一篇新的Blog。工作需要规划,写博客也是如此。

需求

①请保持EF上下文的线程唯一。防止脏临时数据的出现

②请对程序扩展性做好设计。以后ef框架可能改为Spring框架

③服务层调用仓储层时。DBContext为统一入口

    ③.1 方便程序员开发,提供统一入口。把ef封装到此入口里面。

    ③.2防止脏临时数据的出现,“也”请保持这个入口的线程内唯一。

    ③.3要这个统一入口去除服务层和仓储层的耦合

思路

①把ef放进CallContext内。键值对形式存放。

②面向接口的思想

 新建一个工厂接口+工厂。用一个“工厂方法”模式,非“简单工厂”,也非“抽象工厂”设计模式。如果您对工厂的几个设计模式不了解,请参考我写过的设计模式一篇blog。

③ ③.1新建一个类,命名DBContact里面的一个属性类型为ObjectContext,因为上下文继承ObjectContext,继而“点”多个仓储。 

    ③.2放进CallContext内。键值对存储。

    ③.3新建一个IDBContact接口,让DBContact继承。用一个工厂继承一个接口工厂创建。“工厂方法”设计模式

思想

面向接口+工厂模式+线程唯一 2个抽象方法工厂作用:线程唯一+扩展性(面向接口)

 

详情代码

ISingleEFCntextFactory.cs

 

using System.Data.Objects;

namespace LKBS.CommunicationPlatform.IDAL
{
 public interface ISingleEFCntextFactory
 {//no public
 ObjectContext GetCurrentEFContext();
 }
}

 

SingleEFCntextFactory.cs

using LKBS.CommunicationPlatform.IDAL;
using System.Data.Objects;//添加引用 System.Data.Entity
using System.Runtime.Remoting.Messaging;
using LKBS.CommunicationPlatform.Model;


namespace LKBS.CommunicationPlatform.Factory
{
 public class SingleEFCntextFactory : ISingleEFCntextFactory
 {
  public ObjectContext GetCurrentEFContext()
  {
   //把上下文(基类)放在一个线程内。让一次请求(一个ACTION)可能执行CRUD中的几步,公用一个上下文.
   ObjectContext callEFContext = (ObjectContext)CallContext.GetData("efContext");//线程槽 存放“键值对”
   //先读后写。没有就new一个上下文
   if (callEFContext == null)
   {
    callEFContext = new ModelContainer();
   }
   CallContext.SetData("efContext", callEFContext);
   return callEFContext;
  }
 }
}

BaseRespository.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data.Entity;
using LKBS.CommunicationPlatform.Model;
using LKBS.CommunicationPlatform.IDAL;
using System.Data;
using LKBS.CommunicationPlatform.Factory;
using System.Data.Objects;


namespace LKBS.CommunicationPlatform.DAL
{
   public class BaseRespository<T> where T : class,new()
   {
      ISingleEFCntextFactory singleEFFactory = new SingleEFCntextFactory();
      //中间加一个工厂,这里“去除”ef和具体仓储的耦合。可以更换ef。而Respositiry db不用变
      ObjectContext db;//如果没赋值,那就是赋值的问题。找对应赋值的工厂 或者工厂还没编译
      public BaseRespository()
      {
         ObjectContext db = singleEFFactory.GetCurrentEFContext();
      }

      //ModelContainer db = efFactory.GetCurrentEFContext();
      //字段初始值无法引用非静态字段、方法或属性.
      //那我们在构造方法内赋值
....CRUD
    }
}

为方便业务逻辑层调用,建立统一入口。

IDBContact.cs

using System.Data.Objects;//上下文在的空间

namespace LKBS.CommunicationPlatform.IDAL
{
  public interface IDBContact
   {
    //接口中的属性要{}
    ObjectContext currentEFContext { get; set; }
    IUserInforRespository userinforResponsity { get; set; }
    //...多个其他表的仓储,在T4模板中加OK
   }
}

DBContact.cs

using LKBS.CommunicationPlatform.IDAL;
using System.Data.Objects;//上下文的命名空间
using LKBS.CommunicationPlatform.Factory;

namespace LKBS.CommunicationPlatform.DAL
{
 public class DBContact : IDBContact
 {
  public ObjectContext currentEFContext { get; set; }
  ISingleEFCntextFactory singleEFCntextFactory = new SingleEFCntextFactory();//SingleEFCntextFactory做到单一上下文
  public DBContact()
  {
   currentEFContext = singleEFCntextFactory.GetCurrentEFContext();//
  }
  public IUserInforRespository userinforResponsity { get; set; }
 }
}

ISingleDBContactFactory.cs

namespace LKBS.CommunicationPlatform.IDAL
{
  public interface ISingleDBContactFactory
   {
      IDBContact CreateDBCotactUseEF();
   }
}

SingleDBContactFactory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using LKBS.CommunicationPlatform.IDAL;
using System.Data.Objects;
using System.Runtime.Remoting.Messaging;
using LKBS.CommunicationPlatform.DAL;


namespace LKBS.CommunicationPlatform.Factory
{
   //继承接口①接口要编译过,②引入接口所用的程序集+ using
   class SingleDBContactFactory : ISingleDBContactFactory
   {
      public IDBContact CreateDBCotactUseEF()
      {
         //ObjectContext currentEFContext = new ObjectContext("currentEFContext");
         //return currentEFContext;
         IDBContact dbCotact = (DBContact)CallContext.GetData("currentDBContact");
         if (dbCotact==null)
         {
            dbCotact = new DBContact();
         }
         CallContext.SetData("currentDBContact", dbCotact);
         return dbCotact;

      }
   }
}

 

  

 

posted on 2015-05-19 15:51  李可在江湖  阅读(2149)  评论(2编辑  收藏  举报