(转)自己来控制EntityFramework4.1 Code-First,逐步消除EF之怪异现象
转自:http://www.cnblogs.com/richwong/archive/2011/07/06/2098759.html
最近的项目开始使用EF4.1,拜读各路大侠文章数遍,满以为可以轻车熟路,却屡遭悲惨啊,怪异现象接连...
1,虽然使用Code-First模式,就是因为它代码整洁清爽条理,但还是习惯先建立数据表,再POCO... 结果发现Entity实体类与数据表的映射是EF自己独特智能操控的,比如实体类名为Product,它会智能映射成Products的表,加了个"s",然而,Category的实体类却映射成了Categories, 它居然能识别单词的复数写法,很神奇,难道它内置词典?要不然它该映射成Categorys才合理嘛(虽然它不是个单词),你说EF神奇么,真神奇!
后来,同事给个方法,解决了这个神奇的功能,我要自控,有些关键地方不需要EF来控制我的想法,于是在分类名上面添加一个特性[Table("映射的表名")]即可。
[Table("Product")]public class Product{ public int ID { get; set; } [Required] [Display(Name = "产品名")] public string Name { get; set; } public int CategoryID { get; set; } [Required] [Display(Name = "产品价格")] public Decimal? Price { get; set; } public virtual Category Category { get; set; }}[Table("Category")]public class Category{ public int CategoryID { get; set; } /// <summary> /// 分类名 /// </summary> [Required] [Display(Name = "分类名")] public string CategoryName { get; set; } public Int16 IsDel { get; set; } public virtual ICollection<Product> Products { get; set; }} |
我后来又发现一个终极解决办法,那就是在Model建立的时候,移除EF内部的约定,神奇的约定
protected override void OnModelCreating(DbModelBuilder modelBuilder){ // base.OnModelCreating(modelBuilder); // modelBuilder.Entity<Order>().ToTable("Order"); 和实体类名的Table特性设置相同 // 移除EF的表名公约 modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); // 还可以移除对MetaData表的查询验证 modelBuilder.Conventions.Remove<IncludeMetadataConvention>();} |
2,每次通过EF查询数据库,会先Select ... MetaData,甚至SELECT Count(*) FROM sys.databases WHERE [name]=数据库名,前者的无用查询移除,在上面的OnModelCreating中可以取消了,但后者至今我还没找到办法。可以理解的是:EF之code-first会先查找数据库,如果没有则建立命名空间.CustomContext的库名,所以多了后者的查询,即便我在DbContext的类初始化中指定db名、或者连接字符串名,也是同样结果。而实体类和数据表是映射的,EF将实体类做了Hash计算以比对数据表,当发现实体类与数据表不对应的时候,会更新数据表,故而增加了查询metaData的动作。 其实对于我们固定的开发需求,这些功能,不能被关闭实在消耗性能。
3,EF是默认开启延迟加载,延迟加载的关系表中,必须建立表关系,也就是SQL的FK键。延迟加载非常好用,但存在性能问题,因为延迟加载关联到几个表,就要执行几次数据表查询,而不是一次性查询。这也是从字义上理解的达到一致。否则就属于贪婪加载,即Context上下文里的Include("实体名"),可以实现一次性一条SQL语句查询,但我奇怪的是Include的string参数为啥不是表名,反而是实体名却用字符串来传入。
4,最痛苦的是EF下实体类或表字段外键,命名中不能有"_"?经过我测试也不尽然,虽然我发觉到了这是和关联表定义有关系,可是我仍非常不解,例如:
[Table("Product")]public class Product{ public int ID { get; set; } [Required] [Display(Name = "产品名")] public string Name { get; set; } public int CategoryID { get; set; } [Required] [Display(Name = "产品价格")] public Decimal? Price { get; set; } public virtual Category Category { get; set; }}[Table("Order")]public class Order{ [Key] public int ID { get; set; } public int Product_ID { get; set; } public string Name { get; set; } public string Address { get; set; } public DateTime CreateTime { get; set; } public virtual Product Product { get; set; }} |
这是一对关系表,显然设计的是一张订单中只有一个产品,订单中的Product_ID属性对应产品实体的ID属性,已经在数据库中做好了关系。 我要的结果是:当打开一条订单记录时,联表查询得到该产品ID的产品信息,所以做了延时加载public virtual Product Product { get; set; }
非常怪异的现象是,执行Order实体上下文ToList等操作时,提示Product_ID1列不存在,因为这个字段和属性的确不存在,为什么EF会拼出这个字段来呢? 之所以说不尽然是"_"的原因,因为即使我将属性和字段修改成ProductsID,EF却又报错找不到Product_ID的字段,EF要找的这2个字段本身都不存在。它为什么呢? 只有当这个外键字段为ProductID时才正常,这个非常诡异!!! 慢慢我发现,是public virtual Product Product { get; set; } 这个属性,生成了外键ID对应关系的字段Product_ID,也就是EF自己用了"_"符号,但当写成ProductID时,又没有生成。。。很糊涂。。。
5,继续实验中
总结,EF用起来比较轻松,但掌握住还是比较费劲的,虽说EF把一切都封装好了,但了解它的内幕才能给自己更多的信心,至少目前还不能掌握,还不能控制,总是被EF控制,这并不是什么好事,继续努力!如果你有这方面的知识,分享下吧 :)
补充第4条的“怪异现象”,直接见代码:
[Table("Order")]public class Order{ [Key] public int ID { get; set; } public int Product_ID { get; set; } public string Name { get; set; } public string Address { get; set; } public DateTime CreateTime { get; set; } [ForeignKey("Product_ID")] //增加一个外键特性,并制定外键字段 public virtual Product Product { get; set; }} |
Product_ID是外键字段,关联了Product属性,因为Product的主键是ID,EF自己拼装了一个外键字段为“Product_ID”,所以与实际的字段重复,重命名了“Product_ID1”;而当外键属性为其他时,EF就会自己拼装一个“Product_ID”,所以会找不到这个列;但是当属性为ProductID时,EF不会去拼装外键字段,这一定又是EF的内部约定。所幸的是,现在我可以给Product关联的导航属性一个外键特性就OK了。
(转)自己来控制EntityFramework4.1 Code-First,逐步消除EF之怪异现象的更多相关文章
- 2.简单的Code First例子(EF Code-First系列)
现在假想,我们想要为讴歌学校创建一个应用程序,这个程序需要能够来添加或者更新学生,分数,教师还有课程信息. 代替之前我们的做法:先是创建数据库,现在我们不这么做,我们先来创建领域类,首先我来创建两个简 ...
- 【繁星Code】如何在EF将实体注释写入数据库中
最近在项目中需要把各个字段的释义写到数据库中,该项目已经上线很长时间了,数据库中的字段没有上千也有上百个,要是一个项目一个项目打开然后再去找对应字段查看什么意思,估计要到明年过年了.由于项目中使用En ...
- Code Review 程序员的寄望与哀伤
一个程序员,他写完了代码,在测试环境通过了测试,然后他把它发布到了线上生产环境,但很快就发现在生产环境上出了问题,有潜在的 bug. 事后分析,是生产环境的一些微妙差异,使得这种 bug 场景在线下测 ...
- Code First :使用Entity. Framework编程(8) ----转发 收藏
第8章 Code First将走向哪里? So far, this book has covered all of the Code First components that reached the ...
- Code First :使用Entity. Framework编程(6) ----转发 收藏
Chapter6 Controlling Database Location,Creation Process, and Seed Data 第6章 控制数据库位置,创建过程和种子数据 In prev ...
- EntityFramework Reverse POCO Code First 生成器
功能强大的(免费)实体框架工具 Julie Lerman 实体框架是开源的,因此开发社区可以在 entityframework.codeplex.com 上共享代码. 但是不要将自己局限在那里寻找工具 ...
- NK3C 业务权限控制
资源中,添加了一个类型:权限(橙色显示),现在有4种数据: 域管理员:domainAdmin 组织管理员:orgAdmin 组管理员:groupAdmin 一线员工:phoneAdmin 权限控制可以 ...
- EF Code First学习笔记:数据库创建
控制数据库的位置 默认情况下,数据库是创建在localhost\SQLEXPRESS服务器上,并且默认的数据库名为命名空间+context类名,例如我们前面的BreakAway.BreakAwayCo ...
- spring2.5IOC控制反转详解
spring2.5IOC控制反转详解 19. 五 / J2EE / 一条评论 基本的代码结构 1 IOC包下 基本的spring创建对象 将类添加到配置文件中,由容器创建. Source code ...
随机推荐
- linux操作系统-源码包安装jdk1.7
1.下载安装文件 在oracle官方找不到bin二进制安装文件只能使用rpm包来安装 下载地址:http://www.oracle.com/technetwork/java/javase/downlo ...
- Liunx 重定向,管道符(转)
原作网址:http://blog.csdn.net/qq_16811963/article/details/52997178 输出重定向 >代表以覆盖的方式将命令的正确输出输出到指定的文件或设备 ...
- java有车有房有能力最基本运用
public class yunsuan { public static void main(String[] args) { // 1是有,0是没有 int i = 1, l = 0;// 有房 i ...
- Android.DebugTools.Traceview & dmtracedump
1. Android 调试工具之Traceview http://www.cnblogs.com/devinzhang/archive/2011/12/18/2291592.html TraceVie ...
- nested exception is java.lang.NoClassDefFoundError: org/springframework/dao/support/PersistenceExceptionTranslator
该问题是少了一个spring-tx-的jar包,把该包加入到buildpath中就行了. 参考链接:http://blog.csdn.net/Rongbo_J/article/details/4666 ...
- CODE[VS]2494 Vani和Cl2捉迷藏
原题链接 这里有一个结论:最多能选取的藏身点个数等于最小路径可重复点覆盖的路径总数. 所以我们可以先传递闭包,然后求最小路径点覆盖即可. #include<cstdio> #include ...
- BUG(0):用某位表示特定属性
用某个bit表示特定属性通常有两种方式: 1.指定某个特定的value #define _PAGE_VALID 0x0001 0bit 为 1 时表示此时的page entry是有效的 用法如下,此时 ...
- Python之路(第十六篇)xml模块、datetime模块
一.xml模块 xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单, xml比较早,早期许多软件都是用xml,至今很多传统公司如金融行业的很多系统的接口还主要 ...
- linux上的工具或软件
1.下载软件 yum install axelaxel http://mirror.cse.iitk.ac.in/archlinux/iso/2015.04.01/archlinux-2015.04. ...
- nginx的hash
hash结构中有若干个桶,桶内是hash(key)值相同的若干数据. 查找数据时,首先对key值进行hash计算,然后hash值对桶的个数进行求余,得到数据所在的桶.然后在桶中使用key逐个查找,直到 ...