最近的项目开始使用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之怪异现象相关推荐

  1. 如何在团队中做好Code Review

    一.Code Review的好处 想要做好Code Review,必须让参与的工程师充分认识到Code Review的好处 1.互相学习,彼此成就 无论是高手云集的架构师团队,还是以CURD为主的业务 ...

  2. EF Code First学习笔记:数据库创建(转)

    控制数据库的位置 默认情况下,数据库是创建在localhost\SQLEXPRESS服务器上,并且默认的数据库名为命名空间+context类名,例如我们前面的BreakAway.BreakAwayCo ...

  3. Code First :使用Entity. Framework编程(6) ----转发 收藏

    Chapter6 Controlling Database Location,Creation Process, and Seed Data 第6章 控制数据库位置,创建过程和种子数据 In prev ...

  4. Visual Studio Code(VS Code)与Git Source Control集成

    This article explores Visual Studio Code integration with Git Source Control. 本文探讨了Visual Studio Cod ...

  5. Notes Twelfth Day-渗透攻击-红队-命令与控制

    ** Notes Twelfth Day-渗透攻击-红队-打入内网(dayu) ** 作者:大余 时间:2020-09-28 请注意:对于所有笔记中复现的这些终端或者服务器,都是自行搭建的环境进行渗透 ...

  6. 自动驾驶车辆控制测评标准

    自动驾驶中,车辆控制是基础,以什么指标来测评就显的很关键,以下是Apollo 车辆控制评测分析指标,可以在此基础上做裁剪,来满足自己自动驾驶车辆控制的需求. 序号 参数 名称 说明 平均控制性能相关参 ...

  7. STM32CubeIDE 统计及控制PWM产生个数

    STM32 HAL库有两个PWM中断回调函数 void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) : PWM脉冲在非阻塞模式 ...

  8. 应用8255A控制LED小灯开闭(附代码注释)

    设8255A的A口和B口都工作在方式0,A口作为输出口,接有8个开关;B口为输出口,接有8个发光二极管.系统硬件电路中不断扫描开关Ki,当K0闭合时,点亮LED0,LED2,LED4,LED6,其他L ...

  9. 单片机自动调光C语言,基于51单片机的DS18B20水温PID控制调节系统设计C语言程序...

    #include 'reg52.h' #include 'stdio.h' #define uchar unsigned char #define uint unsigned int sbit s1= ...

  10. python控制灯泡_人工智能应用-手把手教你用Python硬件编程实现打开或关闭电灯泡...

    之前我们已经给广大爱好者或程序员朋友们,带来了硬件版的或者说物联网版本的Hello World C++Builder版.Delphi.Visual Basic.Net等的程序源码和教学资料,让大家对硬 ...

最新文章

  1. 翻译BonoboService官网的安装教程
  2. leetcode算法题--最长快乐字符串★
  3. JSP(1)—基础知识
  4. angular中的依赖注入
  5. 星空下的痕迹 Jenkins学习(四)----------windows下Publish over FTP插件应用
  6. matlab数字滤波器设计函数汇总(转载)
  7. html5内容切换特效,html5+jQuery图片和文字内容同时左右切换特效
  8. POJ 3608 Bridge Across Islands 《挑战程序设计竞赛》
  9. SpringCloudGateway 集成 nacos 整合实现动态路由_04
  10. MCSE2003学习之八
  11. java的继承关系linkedlist_LinkedList——JAVA成长之路
  12. vue实现对数据的增删改查(CURD)
  13. 如何给一家公司做定性研究?
  14. WEB环境下打印报表的CRYSTAL的解决方案
  15. 直播网站源码,简洁的登录页面
  16. 指数族分布(2):矩母函数、累积量生成函数
  17. 第十届全国大学生GIS应用技能大赛上午(试题及参考答案)
  18. 4K分辨率是什么 你真的知道吗?
  19. numpy_abs和fabs
  20. PgSql之操作JSON类型字段

热门文章

  1. 计算机网络技术评估与备选方案,创业学复习提纲
  2. Materials Studio教程(中科大)
  3. 抖音上热门运营技巧秘诀
  4. 解决Adobe Reader 打开PDF文件10秒左右自动关闭问题
  5. JavaScript - 360浏览器默认使用极速模式打开网页
  6. RPM包安装卸载命令
  7. 21年6月阿里巴巴Java暑期实习面经回顾(已上岸)
  8. wireshark:包重组
  9. 别了,腾讯!别了,深圳!我去老家当富豪了!
  10. 山东理工大学ACM平台题答案关于C语言 1543 Egypt