0

我有一个 ASP.NET 网站项目,直到最近在 App_Code 文件夹中都有所有代码。它使用实体框架 4 作为 ORM。应用程序分为三个“部分”(假设每个客户一个)。每个部分都有自己的数据库(但模式相同)。这是由于性能原因,每个数据库都超过 10GB,有数百万行。

每次context创建对象时,都会调用保存部分 ID 的会话变量,并为此上下文选择专有连接字符串。

它看起来像这样(以下是静态Connection类的成员):

public static MyEntities GetEntityContext()
{
    if (HttpContext.Current.Session["section"] == null)
    {
        HttpContext.Current.Response.Redirect("~/Login.aspx");
    }
    var context = new MyEntities(GetEntityConnectionStringForSection((int)HttpContext.Current.Session["section"]);
    return context;
}

private static string GetEntityConnectionStringForSection(int section)
{
    switch (section)
    {
        case 1: return ConfigurationManager.ConnectionStrings["entity_1"].ConnectionString;
        case 2: return ConfigurationManager.ConnectionStrings["entity_2"].ConnectionString;
        case 3: return ConfigurationManager.ConnectionStrings["entity_3"].ConnectionString;
        default: return ConfigurationManager.ConnectionStrings["entity_1"].ConnectionString;
    }
}

它工作得非常好,并且还可以处理每次执行任何数据访问时会话超时的情况。

最近,由于我需要在两个网站之间共享 DB 类,我将所有 DB 类移动到单独的类库和引用System.Web库中,我知道这是不好的做法,但它正在工作。

现在下一步是包含单元和模块测试,因为我读到HttpContext在库中使用这些测试非常困难或不可能,所以我想摆脱System.Web引用。这种情况的最佳做法是什么?

我想我不能只是传递HttpContext给它,GetEntityContext()因为它也是从我的实体类中调用的。尽管这可能可以重构。所以也许这就是我应该去的地方?

我还想知道是否有可能以某种方式将当前部分 ID 传递给整个库?它不能只是静态属性,因为据我了解,它对于所有使用该应用程序的用户来说都是常见的。这应该是用户特定的。

重新假设目标是使自动化测试成为可能,而不会丢失透明的连接字符串选择和会话超时处理。

如果我在这个阶段做错了什么,也请告诉我。我可以在明天早上(世界标准时间上午 8 点)再次查看这个问题,所以在此之前请不要因为我的沉默而气馁。

编辑:

Connection库中类的使用示例:

public partial class Store
{
    public static List<Store> GetSpecialStores()
    {
        using (var context = Connection.GetEntityContext())
        {
          return context.Stores.Where(qq => qq.Type > 0).OrderBy(qq => qq.Code).ToList();
        }
    }
}
4

1 回答 1

1

IContextProvider您可以在库中声明接口并使用它来检索上下文。就像是:

public interface IContextProvider
{
   MyEntities GetEntityContext();
}

这将使您的库可测试。在您的 Web 项目中,您可以将IContextProvider实现注入到您的库中。

public class WebContextProvider : IContextProvider
{
    public MyEntities GetEntityContext()
    {
        if (HttpContext.Current.Session["section"] == null)        
            HttpContext.Current.Response.Redirect("~/Login.aspx");

        int sectionId = (int)HttpContext.Current.Session["section"];
        string connectionString = GetEntityConnectionStringForSection(sectionId);
        var context = new MyEntities(connectionString);
        return context;
    }

   private static string GetEntityConnectionStringForSection(int section)
   {
       switch (section)
       {
          case 1: return ConfigurationManager.ConnectionStrings["entity_1"].ConnectionString;
          case 2: return ConfigurationManager.ConnectionStrings["entity_2"].ConnectionString;
          case 3: return ConfigurationManager.ConnectionStrings["entity_3"].ConnectionString;
          default: return ConfigurationManager.ConnectionStrings["entity_1"].ConnectionString;
       }
   }
}

将此接口注入到存储库或其他数据访问类。

public partial class Store
{
    private IContextProvider contextProvider;

    public Store(IContextProvider contextProvider)
    {
        this.contextProvider = contextProvider;
    }

    public List<Store> GetSpecialStores()
    {
        using (var context = contextProvider.GetEntityContext())
        {
          return context.Stores.Where(qq => qq.Type > 0).OrderBy(qq => qq.Code).ToList();
        }
    }
}
于 2012-07-19T14:59:41.960 回答