0

我们目前正在开发一个多租户应用程序,该应用程序在处理多租户方面时遇到了一些随机的奇怪行为。

背景:我们有一个供多组最终用户使用的 ASP.NET 应用程序。他们用来访问应用程序的 URL 决定了他们与哪个公司相关联,并最终决定了他们的数据库连接字符串。我们存储将特定公司 ID 映射到主机名的 CompanyHost 映射的静态列表。如果我们在静态列表中找不到匹配项,我们会从数据库中重新提取列表。

当应用程序第一次启动时,它会正确地拉起连接,为主机找到正确的公司 ID。但是,在一段未知的时间之后,应用程序将开始为所有主机头返回一个空 ID,即使它们存在于数据库中,导致应用程序无法确定连接字符串。进入服务器并回收应用程序池可以解决问题。我试图将应用程序池回收时间设置为低(2 小时)以尝试避免它,但它要么不够低,要么不是问题。

这是按主机获取公司 ID 的片段。即使对于有效的主机名,这也会返回一个空 Guid。

private static List<CompanyHost> lCompanyHosts = new List<CompanyHost>();

public static string Host
{
    get { return HttpContext.Current.Request.Url.DnsSafeHost; }
}

public static Guid CompanyIDByHost
{
    get
    {
        Guid gCompany_ID = Guid.Empty;

        lock (lCompanyHosts)
        {
            if (lCompanyHosts.Count == 0)
                lCompanyHosts = new CompanyHostDataLogic().RetrieveAll();

            gCompany_ID = lCompanyHosts.Where(ch => ch.hostname.ToLower() == Host.ToLower()).Select(ch => ch.company_id).FirstOrDefault();

            if (gCompany_ID == Guid.Empty)
            {
                lCompanyHosts = new CompanyHostDataLogic().RetrieveAll();
                gCompany_ID = lCompanyHosts.Where(ch => ch.hostname.ToLower() == Host.ToLower()).Select(ch => ch.company_id).FirstOrDefault();
            }
        }

        return gCompany_ID;
    }
}

我很难理解为什么这会在正常工作一段时间后返回有效主机的 Guid Empty。我最好的猜测是它与导致问题的网站上一段时间的不活动有关。但是,我不确定解决此问题的最佳方法。

是否有我遗漏的东西或者是否有更好的方法来实现这种类型的功能?

4

2 回答 2

0

这始于评论,但我认为它将受益于代码格式化。这不是一个完整的答案,但使用这种方法可能会得到更好的结果:

RetrieveAll()吞咽有问题吗?当一个新的主机名出现时,您将重置整个列表,lCompanyHosts但如果失败,您将失去一切。也许最好添加一个方法来CompanyHostDataLogic检索单个“CompanyHost”,然后将其添加到您的List<CompanyHost> lCompanyHosts

        if (lCompanyHosts.Count == 0)
            lCompanyHosts = new CompanyHostDataLogic().RetrieveAll();

        gCompany_ID = lCompanyHosts.Where
                        (ch => ch.hostname.ToLower() == Host.ToLower())
                        .Select(ch => ch.company_id).FirstOrDefault();

        if (gCompany_ID == Guid.Empty)
        {
            CompanyHost newEntry = 
                          new CompanyHostDataLogic().RetrieveOne(string Host);
            if(newEntry!=null)
                lCompanyHosts.Add(newEntry);

            gCompany_ID = lCompanyHosts.Where
                           (ch => ch.hostname.ToLower() == Host.ToLower())
                           .Select(ch => ch.company_id).FirstOrDefault();

        }

如果您无法进行任何更改,CompanyHostDataLogic那么您可以将结果RetrieveAll()与现有列表合并。原理是一样的:不要重置现有列表,只需向其中添加任何新的或更新的值。

于 2012-05-09T19:05:35.027 回答
0

最终的问题和我的解决方案的最终答案是,这个过程是在应用程序池启动时触发的。在存在实际请求之前,因此用作键的主机名为空。

这导致了我们看到的错误的奇怪行为。

After changing the initial load to a static object and then adding the dynamic load in as a lazy load it resolved the issue.

于 2012-09-20T20:25:05.893 回答