Структура карты InstanceScope.Hybrid с asp.net MVC ведет себя плохо - PullRequest
0 голосов
/ 26 марта 2009

Я действительно застрял здесь.

У меня есть приложение 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.GetHashCode () + "" + DateTime.Now.ToString ());

где 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 - это хеш-код для текста данных каждый раз для каждого запроса, но служба и хранилище каждый раз получают новый экземпляр и хеш-код.

Я получаю странные ошибки из-за этого, например, исключение dataconcurrency, потому что dbcontext имеет исходное значение 4 веб-запросов назад, тогда как база данных была изменена другим источником.

Ответы [ 3 ]

3 голосов
/ 18 июля 2009

Если вы пытаетесь заставить SM создать один DataContext для HttpRequest, ваша новая конфигурация Registry должна работать

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

InstanceScope.Hybrid - это значение перечисления SM (v2.5.3), которое вы должны использовать, если хотите иметь жизненный цикл «один раз на поток или запрос ASP.NET» (давайте перейдем к источнику Чад Майерс , SM участник )

Если вы правильно сконфигурировали инфраструктуру своего приложения, вам не нужно «менять много кода». Мне было бы интересно узнать, почему вы решили создать класс-оболочку для SharpShopDataContext? LinqToSql DataContext объявлен как частичный класс, так что вы можете легко создать SharpShopDataContext частичный класс, который реализует любые дополнительные интерфейсы:

LinqToSql сгенерированное частичное определение класса

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

Ваше частичное определение класса

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

Возможно, вам стоит почитать некоторые из статей Джереми Миллера StructureMap . Как только вы хорошо разберетесь в его возможностях, вы, вероятно, проведете рефакторинг всего приложения MVC. Я знаю, что моя текущая базовая инфраструктура приложений MVC легко настраивается / тестируется благодаря SM IoC (и множеству проб / ошибок / запаха / рефакторинга).

2 голосов
/ 27 марта 2009

Это определенно проблемная строка:

.TheDefault.IsThis

Вы указываете конкретный экземпляр, именно поэтому он возвращает то же самое, даже если указывает PerRequest. Обратите внимание, что вы изменили (в вашем обходном пути):

.TheDefaultIsConcreteType<SharpShopDataContextWrapper>();

Ps. Я не использовал HybridScope, но у меня есть производственное приложение, которое использует область экземпляра по умолчанию (PerRequest), и она определенно выдает новую каждый раз, когда передает текстовый текст. Если вы хотите конкретно контролировать, как оно создается, попробуйте один из методов, которые принимают выражение, таким образом вы отправляете:

() => new MyDataContext()
0 голосов
/ 26 марта 2009

У меня есть обходной путь, но я не рад этому, потому что знаю, что мне нужно изменить много кода, и я обнаружил его методом проб и ошибок.

Я сейчас использую:

            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; }
    }
}
...