看到标题可能已经要受到批评指正:Code First提倡的就是先用面向对象方式建模然后由EF自动生成数据库(首先不讨论优劣性,个人一直很向往这种设计方式),如果先数据库建模再生成实体模型当然用VS2010的EF模板再全选拖拓拽表生成更方便,而且是正道…...但除了钻牛角尖以外,也不乏真正需要这样做的场景,这里先不讨论这些。回到正题,也当是对Code First方式做个进一步的了解吧,呵呵。
(本文假设您已经了解EF和Code First,当然你也可以到博客园里找找其它High Hand的blog)
在默认情况下,当你实现自己的数据库上下文后,如果对上下文进行CRUD操作后,EF将自动根据上下文的定义自动生成数据库(或连接到现有数据库)。可能最容易被人忽略的问题就是:生成的库的名字是怎样确定的?表名又是怎样确定的?因为这两个问题直接决定了是产生数据库还是连接到原有数据库甚至可能会抛异常。回到咱们主题,我们的目的是连到现有数据库,所以就从这点出发分析其原理。
首先说说数据库名字,当数据库上下文对象是使用默认构造器(无参构造)实例化时,数据库名将取为自定义数据库上下文(自定义DbContext)的完全限定名,即"命名空间.上下文类名"。如:
数据库名将取为“TopwayAD.Dtv.Data.SqdlDB”。相信80%以上做数据库设计的同志也不会这样来命名数据库:),多半都生成了个新库了吧:)那怎样才能“控制”数据库的命名即连到现有的数据库呢?答案很简单,就是使用数据库上下文带参的构造器,此方法也是使ADO.NET连接字符串可以重用的最直接的方式,当然你不喜欢Code First就另当别论了,呵呵。构造器签名如下:
当调用此构造器实例化数据库上下文时,数据库名将取自连接字符串中数据库名的定义部分。如下图:
再说到表名,表名则会以自定义DbContext中的DbSet泛型属性的实体类型的类型名的复数形式做映射,如果没有找不到则会抛异常!!注意:是实体类的类型名,而不是上下文中的DbSet泛型类型的属性名!如果现有数据库的表名不是实体类的复数形式,则可以在实体类上添加Table特性来指定与哪个表做映射,即[Table("表名")]。如下图:
默认情况数据库需要映射“Areas”表,若上下文数据库中没有该表则会抛异常。
最后对数据库表中字段和实体属性的映射再补充一下,默认表字段跟实体属性名名字一样的做映射,并不区分大小写。当实体存在基类并在基类中定义了属性需要映射(如:Id属性),则需要数据表字段迁就基类,需要将数据库表的相应列改成与基类的属性同名。(此处需要说明,我没研究别的解决方案,如果有请告知)另外的角度看,用ID列为例,建议数据建模时给主键列命名时都统一定义为"ID"而不要使用“实体标识+ID后缀”这样的命名方式。当然外键列名是需要用“实体标识+ID后缀”来命名的。
有关其它的默认规则可以查看:Code First中的约定 http://blog.joycode.com/saucer/archives/2010/10/08/116098.joy
需要更多EF的文档支持可以查看MSDN:Entity Framework 4.1 http://msdn.microsoft.com/en-us/library/gg696172(v=VS.103).aspx
时间关系写到这儿,因为本人对EF和Code First方式的了解只是皮毛,请各位High Hand批评指正。
本文出处:http://www.cnblogs.com/Ryu666/archive/2011/09/18/EFConnectTOExistDB.html