异常跟踪之CLR 类型到 EDM 类型的映射不明确
异常信息:
"指定的架构无效。错误:
CLR 类型到 EDM 类型的映射不明确,因为多个 CLR 类型与 EDM 类型“Person”匹配。
以前找到的是 CLR 类型“A.Person”,
新找到的则是 CLR 类型“B.Person”。
这类异常信息在代码里面出现过几次,每次的解决方案都让人匪夷所思。不知道为什么出现,也不知道为什么被解决了。
查阅了一些国外的资料,链接:
Don't use classes with the same name - EF uses only class names to identify the type mapped in EDMX (namespaces are ignored) - it is a convention to allow mapping classes from different namespaces to single model. The solution for your problem is to name your classes in BLL differently.
但实际情况是,这类异常不总是出现,而是在一个偶然的情况下出现。所谓偶然的情况,却是一种很普通又简单的调用。
using (var con = new MyContainer())
{
string sql = "select top 1 name from cat";
var p = con.Database.SqlQuery<contract.Dog>(sql).FirstOrDefault();
Console.WriteLine(p.Name);
}
查询cat数据,将第一个的name数据查询并存储在contract.Dog对象中。这类调用非常普通。
整理一下思路:
1. 出现"CLR 类型到 EDM 类型的映射不明确"异常,肯定是存在和ef模型中数据结构一样的类。
2. 与ef数据结构同名的类一直存在,但并非一直报错。
做以下测试:
测试一
在ef数据模型所在项目中(以下用entity表示),建立模型Person

同时,在entity项目中另外新建一个类,也命名为Person(当然名称空间不一样),属性一样(类型和名称)。
调试时,会发现报错,报错内容同上。
测试二
在测试一的基础上,去掉entity中手动创建的Person类,在解决方案下新建另一个项目contract,在contract中新建类,命名Person,属性同上。
调用代码:
using (var con = new MyContainer())
{
string sql = "select top 1 * from person";
var p = con.Database.SqlQuery<contract.Person>(sql).FirstOrDefault();
Console.WriteLine(p.Name);
}
单独运行这段时,不会报错。加上下面这段:
using (var con = new MyContainer())
{
string sql = "select top 1 * from person";
var p = con.Database.SqlQuery<efentity.Person>(sql).FirstOrDefault();
Console.WriteLine(p.Name);
}
执行完上面代码后,紧接着执行下面的代码。出现异常,异常同上。
加断点,跟踪con的数据明细。
在执行完第一段查询以前,con.base._internalContext.ObjectContext.MetadataWorkSpace._itemOCSpace.Value(以下简称MetaOCSpace)为空;
执行完第一段查询后,MetaOCSpace的数量出现32条,具体如下:

出现了Person的类型映射数据,此时Person类型映射到了contract.Person。
省略其他测试过程,有如下结论:
1. 当entity中出现同数据模型的类时,同类名同字段,无论什么时候用ef操作数据,都会报错。
2. 当entity所在的assembly没有同名类,但其他assembly(例contract)有同名类时。先有查询结果放入entity的任意类对象,后有查询结果放入contract的任意类对象时,就会报错。操作的先后顺序调换,结果一样。
这是因为DbContext的MetadataWorkSpace一旦生成会缓存起来。也就是说,在同一个应用程序域里面,一旦用dbcontext操作过数据库,它会自动读取类所在assembly里面的所有类,并尝试匹配数据库模型,然后将匹配结果保存起来(保存到上面的MetaOCSpace中)。当下次操作数据库时,返回数据对应类类所在其它assembly里面的类与当前已匹配数据库模型发生冲突时,便会报错。
3. 当client引用entity + client引用contract时,有结论2的隐患。而当entity引用contract,然后client引用entity时,同样存在问题。
这种情况一般出现在ef的枚举类型定义为引用外部类型(contract中定义的类型),这时就会出现entity引用contract,然后client引用entity的场景。配合以下代码:
using (var con = new MyContainer())
{
var p = con.Person.Where(pp => pp.Status == contract.We.One).FirstOrDefault();
Console.WriteLine(p.Name);
}
这时,也会出现报错。
解决思路:
1. 不要与entity中的模型同名,同字段。或者换过来entity中的模型加特殊标记
2. ef操作数据库时,返回数据的数据类型必须用entity项目中定义的类型。
以上内容,部分细节未仔细推敲,如有其他想法请留言。
异常跟踪之CLR 类型到 EDM 类型的映射不明确的更多相关文章
- 指定的架构无效。错误: CLR 类型到 EDM 类型的映射不明确
在使用WebService开发时,同时使用了EF和linq,查询数据时,使用linq(查询订单)可以正常拉出数据, 但是使用EF(查询用户)却会报以下错误: {"指定的架构无效.错误: \r ...
- [CLR via C#]4. 类型基础及类型、对象、栈和堆运行时的相互联系
原文:[CLR via C#]4. 类型基础及类型.对象.栈和堆运行时的相互联系 CLR要求所有类型最终都要从System.Object派生.也就是所,下面的两个定义是完全相同的, //隐式派生自Sy ...
- CLR:基元类型、引用类型和值类型
最新更新请访问: http://denghejun.github.io 前言 今天重新看了下关于CLR基元类型的东西,觉得还是有必要将其记录下来,毕竟这是理解CLR成功 之路上的重要一步,希望你也 ...
- [CLR via C#]6. 类型和成员基础
原文:[CLR via C#]6. 类型和成员基础 6.1 类型的各种成员 在一个类型中,可以定义0个或多个以下种类的成员: 1)常量 常量就是指出数据值恒定不变的符号.这些符号通常用于使代码更 ...
- [Clr via C#读书笔记]Cp5基元类型引用类型值类型
Cp5基元类型引用类型值类型 基元类型 编译器直接支持的类型,基元类型直接映射到FCL中存在的类型. 作者希望使用FCL类型名称而避免使用关键字.他的理由是为了更加的清晰的知道自己写的类型是哪种.但是 ...
- 重温CLR(三)类型基础
所有类型都从System.Object派生 “运行时”要求每个类型最终都要从System.Object类型派生.也就是说,一下两个类型的定义完全一致. //隐式派生自Object class Empl ...
- 【CLR Via C#】15 枚举类型与位类型
1.基础 枚举类型(enumerated types)定义了一组“符号名称/值”配对. 枚举类型是值类型,每个枚举类型都是从System.Enum派生的,而System.Enum又是从System.V ...
- C#中的基元类型、值类型和引用类型
C# 中的基元类型.值类型和引用类型 1. 基元类型(Primitive Type) 编译器直接支持的类型称为基元类型.基元类型可以直接映射到 FCL 中存在的类型.例如,int a = 10 中的 ...
- CLR-2-2-引用类型和值类型
引用类型和值类型,是一个老生常谈的问题了.装箱拆箱相信也是猿猿都知,但是还是跟着CLR via C#加深下印象,看有没有什么更加根本和以前被忽略的知识点. 引用类型: 引用类型有哪些这里不过多赘述,来 ...
随机推荐
- MySQL prepare 原理
Prepare的好处 Prepare SQL产生的原因.首先从mysql服务器执行sql的过程开始讲起,SQL执行过程包括以下阶段 词法分析->语法分析->语义分析->执行计划优化 ...
- 记一次SQLServer数据库误删数据找回
昨天 同事在本机清理数据库表时,连接到了生产机,误删了二十几张表,幸好是晚上加班的时候删除的,生产机上当时是一天一备份,还原备份是最后的策略,最关键的还是要找回数据. ...
- 从RTSP协议SDP数据中获得二进制的SPS、PPS
在RTSP协议的交互过程中,第二步客户端发送DESCRIBE请求之后,服务端会返回SDP内容,该SDP内容中有关于媒体和会话的描述,本篇文章主要给出如何从SDP字符串中得到H264视频信息中的sps. ...
- 大熊君说说JS与设计模式之------策略模式Strategy
一,总体概要 1,笔者浅谈 策略模式,又叫算法簇模式,就是定义了不同的算法,并且之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 策略模式和工厂模式有一定的类似,策略模式相对简单容易理解,并 ...
- 将GitLab的数据库导入阿里云PostgreSQL RDS
GitLab的数据库用的是PostgreSQL,之前由于阿里云RDS不支持PostgreSQL,只能将GitLab的数据库部署在云服务器上. 6月1日得知阿里云推出了PostgreSQL RDS,于是 ...
- spring MVC注解深入研究
@Controller @Service @Controller和 @Component注册一个action 到spring 上下文中,bean 的ID 默认为类名称开头字母小写.@Reposito ...
- Ubuntu 安装配置MySQL,并使用VS的Server Explorer UI界面远程管理MySQL
为安装配置方便,使用root账号登入Ubuntu. step1: 键入下面命令安装MySQL. 过程十分简单.安装过程中只需根据提示输入root账号的密码即可. step2:安装完成后检查MySQL是 ...
- Lucene
Lucene 是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎. Lucene的目的是为软件开发人员提供一个简单易 ...
- webview长按事件js监听
做app开发时,用到了webview,需要监听webview的长按事件,使用原生的js处理监听如下: ; //定时器 //开始按 function gtouchstart() { timeOutEve ...
- spring源码 — 二、从容器中获取Bean
getBean 上一节中说明了容器的初始化,也就是把Bean的定义GenericBeanDefinition放到了容器中,但是并没有初始化这些Bean.那么Bean什么时候会初始化呢? 在程序第一个主 ...