0

我真的被困在这里了。

我有一个 asp.net mvc 应用程序并使用 StructureMap 2.5.3 (SM) 在我的控制器中注入服务和存储库类。所有控制器均由 SM 工厂制造。

我还有一个 Linq to SQL 数据上下文,我想通过混合进行缓存。

public class DBRegistry:Registry
{
    public  DBRegistry()
    {
        ForRequestedType<SharpShopDataContext>()
            .CacheBy(StructureMap.Attributes.InstanceScope.Hybrid)
            .TheDefault.IsThis(new SharpShopDataContext());
    }
}

缓存似乎不起作用,因此我遇到了数据上下文问题。

多个浏览器请求都返回相同的dbcontext?!在我的一个存储库类中,我放置了这段代码。Debug.WriteLine("db hashcode: " + db.GetHashCode()+ " "+ DateTime.Now.ToString());

其中 db=datacontext 我还使用 db 打印存储库的哈希码,使用存储库打印服务,这里是多个请求的打印:

服务哈希码:6238972 26-3-2009 18:59:34

存储库哈希码:21756593 26-3-2009 18:59:34

数据库哈希码:7043935 26-3-2009 18:59:34

服务哈希码:59389065 26-3-2009 18:59:34

存储库哈希码:8331620 26-3-2009 18:59:34

数据库哈希码:7043935 26-3-2009 18:59:34

服务哈希码:11291358 26-3-2009 18:59:38

存储库哈希码:13848497 26-3-2009 18:59:38

数据库哈希码:7043935 26-3-2009 18:59:38

服务哈希码:42509361 26-3-2009 18:59:38

存储库哈希码:56101068 26-3-2009 18:59:38

数据库哈希码:7043935 26-3-2009 18:59:38

如您所见,7043935 是每次请求的数据上下文的哈希码,但服务和存储库每次都会获得一个新实例和哈希码。

因此,我得到了奇怪的错误,例如数据并发异常,因为 dbcontext 具有 4 个 webrequests 前的原始值,而数据库被另一个源更改。

4

3 回答 3

3

如果您试图让 SM 为DataContext每个 HttpRequest 创建一个,那么您的新Registry配置应该可以工作

ForRequestedType<ISharpShopDataContextWrapper>()
            .CacheBy(StructureMap.Attributes.InstanceScope.Hybrid)
            .TheDefaultIsConcreteType<SharpShopDataContextWrapper>();

InstanceScope.Hybrid如果您想要“每个线程或 ASP.NET 请求一次”生命周期,您应该使用 SM (v2.5.3) 枚举值(让我们转到源代码Chad Myers,SM贡献者

如果您正确配置应用程序基础架构,则不应“必须更改大量代码”。我很想知道您为什么决定为您的SharpShopDataContext? LinqToSqlDataContext被声明为分部类,因此您可以轻松创建SharpShopDataContext实现任何附加接口的分部类:

LinqToSql生成的部分类定义

public partial class SharpShopDataContext: System.Data.Linq.DataContext{
    /*Linq2Sql gen here*/
}

您的部分类定义

public partial class SharpShopDataContext: ISharpShopDataContext{
   /*your implementation here*/
}

您可以考虑阅读一些Jeremy Miller 的 StructureMap 文章。一旦你很好地理解了它的功能,你可能会重构你的整个 MVC 应用程序。我知道我当前的基本 MVC 应用程序框架是高度可配置/可测试的,因为 SM IoC(以及大量试验/错误/气味/重构)。

于 2009-07-18T04:57:57.170 回答
2

这绝对是一个问题线:

.TheDefault.IsThis

您正在指定一个特定的实例,这就是导致它返回相同的原因,即使指定 PerRequest。请注意,您更改为(在您的解决方法中):

.TheDefaultIsConcreteType<SharpShopDataContextWrapper>();

附言。我没有使用过 HybridScope,但我有一个使用默认实例范围 (PerRequest) 的生产应用程序,并且每次传递数据上下文时它肯定会给出一个新的应用程序。如果您想具体控制它的实例化方式,请尝试其中一种接受表达式的方法,即您发送的方式:

() => new MyDataContext()
于 2009-03-26T21:04:16.707 回答
0

我有一个解决方法,但对此并不满意,因为我知道我必须更改很多代码,而且我通过反复试验发现了它。

我现在使用:

            ForRequestedType<ISharpShopDataContextWrapper>()
            .CacheBy(StructureMap.Attributes.InstanceScope.Hybrid)
            .TheDefaultIsConcreteType<SharpShopDataContextWrapper>();

接口的注入/缓存似乎有效。这是接口+具体包装器的实现。

所以它看起来真的像 SM 中的一个错误,还是我错过了什么?

public interface ISharpShopDataContextWrapper
{
    SharpShopDataContext DataContext
    {
        get;
    }
}

public class SharpShopDataContextWrapper : ISharpShopDataContextWrapper
{
    SharpShopDataContext db;

    public SharpShopDataContextWrapper()
    {
        db = new SharpShopDataContext();
    }
    public SharpShopDataContext DataContext
    {
        get { return db; }
    }
}
于 2009-03-26T20:29:47.790 回答