Указанный листинг из материализованного типа "System.Guid" в тип "System.Int32" недействителен

The specified cast from a materialized 'System.Guid' type to the 'System.Int32' type is not valid.

У нас есть несколько служб WCF, которые имеют режим concurrency для нескольких и InstanceContextMode для Single. Наша архитектура фокусируется на слабосвязанной модели, используя инъекцию зависимостей на основе конструктора. Это, в свою очередь, реализовано с использованием Unity 2.0 (web.config каждой службы имеет сопоставления между интерфейсами и типами, определенными в секции контейнера единиц). Одной из наших зависимостей является сборка DAL (уровень доступа к данным), которая использует Entity Framework 4 для связи с сервером MSSql. Классы, которые ведут разговор с базой данных, также включаются в отображение единства.

Все отлично, когда мы запускаем наши интеграционные тесты. Но когда мы переходим к нашей среде производительности для запуска нагрузочных тестов (2, 3, 4 одновременных пользователя), мы начинаем видеть следующую ошибку:

System.InvalidOperationException: The 'auth_token' property on 'Session' could not be set to a 'Int32' value. You must set this property to a non-null value of type 'Guid'.

Со следующим стеком:

at System.Data.Common.Internal.Materialization.Shaper.ErrorHandlingValueReader`1.GetValue(DbDataReader reader, Int32 ordinal)
at System.Data.Common.Internal.Materialization.Shaper.GetPropertyValueWithErrorHandling[TProperty](Int32 ordinal, String propertyName, String typeName)
at lambda_method(Closure , Shaper )
at System.Data.Common.Internal.Materialization.Shaper.HandleEntityAppendOnly[TEntity](Func`2 constructEntityDelegate, EntityKey entityKey, EntitySet entitySet)
at lambda_method(Closure , Shaper )
at System.Data.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper)
at System.Data.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.MoveNext()
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
at System.Linq.Queryable.First[TSource](IQueryable`1 source)
at MISoa.DataAccessLayer.Authentication.AuthenticationDB.RetrieveSession(Guid authToken)
at MISoa.DataAccessLayer.Authentication.AuthenticationAccess.RetrieveSession(String sessionToken)

Вот метод преступника:

public Session RetrieveSession(Guid authToken)
    {
        CheckDBContext();
        var sessions = (from r in _dbContext.Sessions
                where r.auth_token == authToken
                select r);
        return sessions.Count() > 0 ? sessions.First() : null;
    }

CheckDBContext метод просто проверяет, является ли контекст db нулевым, а если он есть, он генерирует настраиваемое исключение.

Объект сущности объекта Emdx имеет следующие общедоступные свойства:

Guid auth_token
DateTime time_stamp
String user_id
String app_id

Итак, похоже, что приведенный выше linq возвращает другой объект из базы данных, где первый столбец является int, а не guid? И если да - почему? У меня проблема с несколькими потоками, которые переопределяют друг друга? BTW - мы абстрагировали код, который создает контекст db для отдельного класса (BaseDB), который также обрабатывается единством. Итак, поскольку служба является singleton, у меня есть один экземпляр BaseDB для всех, не так ли? Это проблема здесь?

О, еще одна вещь. Нам сказали, что у нас будет MSSql 2005, поэтому в edmx файле у нас есть ProviderManifestToken="2005". Но я только что проверил, и сервер с нашей базой данных производительности - версия 2008. Это проблема?

Благодарим вас за помощь.

Ответы

Ответ 1

У меня проблема с несколькими потоками, которые переопределяют друг друга в db-контексте?

Да. См. Здесь: http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx

Цитата из большой желтой коробки в приведенной выше ссылке:

Класс ObjectContext не является потокобезопасным. Целостность объектов данных в ObjectContext не может быть обеспечена в многопоточных сценариях.

Возможно, вы захотите поместить [ThreadStaticAttribute] в поле _dbContext.

Ответ 2

Я подозреваю, что ваша проблема возникает, когда результатов нет, а нулевое value == 0 используется для сравнения полей Guid где-то в сгенерированном SQL. Попробуйте выполнить сравнение как строку (.ToString() на обоих) и посмотрите, можете ли вы поймать случай, который вызывает вашу проблему.