Указанный листинг из материализованного типа "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() на обоих) и посмотрите, можете ли вы поймать случай, который вызывает вашу проблему.