用过code first的基本上都不会再想用回model first或是db first(谁用谁知道)。不要问我为什么不一开始就直接使用code first,因为那个时候我还不会(甚至还把model first当成了code first)。
因为工作中使用的就是code first,且越用越习惯,越用越喜欢。
原因如果:
- 再也用为每次生成那个笨重的edmx文件性急了
- 再也不用当心保存tt文件而丢失特性、注销、扩展方法了
- 再也不用为了使用微软的验证插件非得写Metadata文件了
- 再也不用为了扩展tt文件生成的实体类去写(partial)部分类了。
- 再也不用为了生成满足自己需要的实体而去修改那些坑爹的tt文件里面的语法代码了(如:默认每个实体继承一个父类)
- 再也不用为了查找edmx文件打不开,去编辑庞大的edmx文件中找那些坑爹的错误了。
- 等等还有些暂时没想到的....
说改就改
修改前实体:db first(由tt文件生成)
修改后实体:code first(完全手写)
然后把实体更新到数据库对应的表结构。执行命令Enable-Migrations
遇到问题:
The EntityFramework package is not installed on project ''.(原因:因为没有选择“默认项目”)
继续问题:
The project 'Blogs.Model' failed to build.(原因:没有建一个继承于DbContext的类)
ok,提示已经启用迁移。
然后我们执行命令:Add-Migration blogs
异常: 从数据库中获取提供程序信息时出错。这可能是 Entity Framework 使用的连接字符串不正确导致的。有关详细信息,请查看内部异常并确保连接字符串正确。
我的乖乖,我非常确定我们字符串链接是正确的啊。
最后确定忘记给数据连接上下文在构造函数中传入配置文件的数据库链接名。
public BlogDbContext() : base("HiBlogsTest") { }
再执行(Add-Migration blogs),再出错:
异常:无法加载指定的元数据资源。(百度之,原来是链接字符串有问题。http://www.cnblogs.com/chengxiaohui/articles/2106765.html)
<add name="HiBlogsTest" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient; provider connection string=" data source=.; initial catalog=HiBlogsTest; user id=sa; password=123qwe; MultipleActiveResultSets=True; App=EntityFramework"" providerName="System.Data.EntityClient" />
改成:(那一堆csdl、ssdl、msl什么都不要了,就留个简单的链接。干净)
<add name="HiBlogsTest" connectionString="Data Source=.;Initial Catalog=HiBlogsTest;User ID=sa;Password=123qwe;" providerName="System.Data.SqlClient" />
ok,终于没有看见红色的字了。
且看到了一个自动生成的blogs文件。且不管,看看数据库是否有表结构。
空空如也。(屁都没看到一个)(原因:BlogDbContext上下文中没有添加实体,没有告诉程序要生成哪些实体到数据库)
给BlogDbContext类添加数据代码:
public class BlogDbContext : DbContext { public BlogDbContext() : base("HiBlogsTest") { } public DbSet<BlogInfo> BlogInfos { get; set; } public DbSet<BlogComment> BlogComments { get; set; } public DbSet<BlogReadInfo> BlogReadInfos { get; set; } public DbSet<BlogTag> BlogTags { get; set; } public DbSet<BlogType> BlogTypes { get; set; } public DbSet<BlogUser> BlogUsers { get; set; } public DbSet<BlogUserInfo> BlogUserInfos { get; set; } }
然后执行 :Add-Migration blogs 再执行 update-database
终于看到表数据了。
有了表还不行,我们还没有主外键。
修改BlogDbContext如下:
public class BlogDbContext : DbContext { public BlogDbContext() : base("HiBlogsTest") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); var entityBlogUser = modelBuilder.Entity<BlogUser>(); entityBlogUser.HasMany(p => p.BlogInfos).WithRequired(t => t.BlogUser) .Map(m => m.MapKey("BlogUserId")); entityBlogUser.HasRequired(p => p.BlogUserInfo).WithRequiredPrincipal(t => t.BlogUser) .Map(m => m.MapKey("BlogUserId")); entityBlogUser.HasMany(p => p.BlogTags).WithRequired(t => t.BlogUser) .Map(m => m.MapKey("BlogUserId")); entityBlogUser.HasMany(p => p.BlogTypes).WithRequired(t => t.BlogUser) .Map(m => m.MapKey("BlogUserId")); entityBlogUser.HasMany(p => p.BlogComments).WithRequired(t => t.BlogUser) .Map(m => m.MapKey("BlogUserId")); var entityBlogInfo = modelBuilder.Entity<BlogInfo>(); entityBlogInfo.HasMany(p => p.BlogTags).WithMany(t => t.BlogInfos) .Map(m => m.ToTable("BlogInfo_BlogTag")); entityBlogInfo.HasMany(p => p.BlogTypes).WithMany(t => t.BlogInfos) .Map(m => m.ToTable("BlogInfo_BlogType")); entityBlogInfo.HasMany(p => p.BlogComments).WithRequired(t => t.BlogInfo) .Map(m => m.MapKey("BlogInfoId")); entityBlogInfo.HasMany(p => p.BlogReadInfos).WithRequired(t => t.BlogInfo) .Map(m => m.MapKey("BlogInfoId")); } public DbSet<BlogInfo> BlogInfos { get; set; } public DbSet<BlogComment> BlogComments { get; set; } public DbSet<BlogReadInfo> BlogReadInfos { get; set; } public DbSet<BlogTag> BlogTags { get; set; } public DbSet<BlogType> BlogTypes { get; set; } public DbSet<BlogUser> BlogUsers { get; set; } public DbSet<BlogUserInfo> BlogUserInfos { get; set; } }