【问题标题】:The specified cast from a materialized 'System.Guid' type to the 'System.Int32' type is not valid从具体化的“System.Guid”类型到“System.Int32”类型的指定转换无效
【发布时间】:2012-05-10 20:59:48
【问题描述】:

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

我们有几个 WCF 服务具有 Multiple 并发模式和 Single 的 InstanceContextMode。我们的架构专注于使用基于构造函数的依赖注入的松散耦合模型。这又是使用 Unity 2.0 实现的(每个服务的 web.config 具有在统一容器部分中定义的接口和类型之间的映射)。我们的依赖项之一是使用 Entity Framework 4 与 MSSql Server 通信的 DAL 程序集(数据访问层)。与数据库对话的类也包含在统一映射中。

当我们运行集成测试时,一切都很好。但是当我们转移到我们的性能环境来运行负载测试(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 方法只检查数据库上下文是否为空,如果是,则抛出自定义异常。

emdx 会话实体对象具有以下公共属性:

Guid auth_token
DateTime time_stamp
String user_id
String app_id

所以,看起来上面的 linq 有时会从数据库中返回一些其他对象,其中第一列是 int 而不是 guid?如果是这样 - 为什么?我是否有多个线程覆盖彼此的数据库上下文的问题?顺便说一句 - 我们将实例化数据库上下文的代码抽象为一个单独的类(BaseDB),该类也由统一处理。所以,因为服务是单例的,所以我为每个人提供了一个 BaseDB 实例,对吧?这是这里的问题吗?

哦,还有一件事。我们被告知我们将拥有 MSSql 2005,所以在 edmx 文件中我们有 ProviderManifestToken="2005"。但是我刚查了一下,我们的性能数据库的服务器是2008版的。这是一个问题吗?

感谢您的帮助。

【问题讨论】:

  • 我要检查的第一件事是:auth_token 是您数据库中的 Guid 吗?该错误表示某些东西正在尝试将 session.auth_token 设置为 int。是否存在未正确映射的 int Id 列?你能做一个 sql 分析跟踪并识别实际的 sql 调用吗?我真的怀疑多线程在这里会导致您的问题。
  • 您确定数据库中的列是对应的属性类型吗?异常表示 DbDataReader 读取 Guid,但您的类上的属性是 int。

标签: c# wcf sql-server-2008 sql-server-2005 entity-framework-4


【解决方案1】:

我是否有多个线程覆盖彼此的数据库上下文的问题?

是的。见这里:http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.aspx

引用以上链接中的黄色大框:

ObjectContext 类不是线程安全的。在多线程场景下无法保证ObjectContext 中数据对象的完整性。

您可能需要考虑将[ThreadStaticAttribute] 放在您的_dbContext 字段中。

【讨论】:

  • 所以主要问题是 ObjectContext 不是线程安全的 - 没关系,但我只想提一下,在 WCF/Asp.Net 中使用时,将 DbContext 属性设为 Threadstatic 可能会导致更多问题,具体取决于主机以及初始化属性的方式(或更好的时间)。例如,当使用 WCF 时,您应该使用 OperationContext 来存储这些内容,因为接受请求的线程可能与执行请求的线程不同。见operationcontext
【解决方案2】:

我怀疑当没有结果时会出现您的问题,并且在生成的 SQL 中的某处将空值 ==0 用于 Guid 字段比较。尝试将比较作为字符串进行(两者都为 .ToString()),看看是否能发现导致问题的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多