2014/9/2 技术探讨

前两回合,我们讨论学习了如何采用Entity Framework在没有数据库的情况下自己写一些实体类,然后通过CodeFirst反向生成对应的数据库。通过CodeFirst,我们摆脱了edmx文件,没有了繁琐的Xml关系映射,使代码变得无比的清晰,修改起来也变得更加容易。

在前两篇文章中,我们的数据库都是通过反向生成的,也就是说,属于一个New Database(新数据库),那么,对于一个Exist Database(已存在的数据库),我们又应该怎么办呢?本节文章,我们将对 Code First to an Existing Database 做出讨论学习。

本回合我们将讨论:

1、介绍使用“Entity Framework Power Tools“ 工具

2、EF CodeFirst to Existing Database 的快速入门

3、了解”Entity Framework Power Tools“ 工具为我们做了哪些事

案例代码可以点击这里下载 


1、Entity Framework Power Tools 工具

在看完本节的导读时,也许你已经有了自己的一点想法:“按照我的数据库结构,自己手写出一些对应的实体Model,然后再写一个继承自DbContext的上下文……”。没错,恭喜你,你的想法理论上确实是可行的,至少在表不太多的情况下是可行的。但是,如果这个数据库的表有很多呢,数目已经达到了上百个或者更多呢?明显的,我们如果想自己手写实体和上下文,那无疑是一件巨大的工程。

既要懂得原理,也要懂得效率;我们要做某一件事,必须先要懂得它的原理,为什么要这么做,知其然知其所以然,所谓“原理先行”嘛。懂了了原理之后,我们需要提高效率,这在当今这个效率就是金钱的时代中尤为重要。

不扯开话题,下面我为大家介绍一款工具,它的名字就是:“Entity Framework Power Tools”,它的可以实现,对数据库中已存在的表自动的生成相应的实体和上下文。这款工具的下载地址各位读者可以点击这里获得最新版的下载。

各位读者下载下来之后,双击打开安装,然后再重启Visual Studio实例,就可以使用啦。

 

2、快速入门(快速案例)

我们新建一个解决方案 

再看看我们的数据库,这里我采用上回合反向生成的数据库(由于VS自带的数据库管理器用起来速度太慢,我额外装了一个“SQL Server Management Studio”,数据库实例还是采用原先的轻量级数据库LocalDB,区别的仅仅是管理工具不同,数据库实例还是一样,各位读者不必感觉疑惑)

右键点击解决方案,我们发现了一些新东西

这就是我们刚才安装的EF工具,顺着点击进去,我们会弹出一个SQL Server的连接窗口,填写好相应的连接信息,点击确定

稍等一会儿,系统会自动的连接数据库,然后遍历所有的表,并根据表结构生成一些代码。

我们可以看到,解决方案中多了一个“Model”文件夹,里面包含有上下文、一些Model、“Mapping”文件夹以及其下的Map文件(映射文件)

我们先不解释里面的东西,先在Program中写调用代码,解释留到第三节再解析。

我们在Program中写如下调用代码:

class Program
    {
        static void Main(string[] args)
        {
            using (var db = new CodeFirst_2013_3_23BlogContextContext())
            {
                Console.Write("Enter a name for a new blog:");
                var name = Console.ReadLine();
                var blog = new Blog { BlogName = name };
                db.Blogs.Add(blog);
                db.SaveChanges();

                var result = from b in db.Blogs
                             select b;
                foreach (var item in result)
                {
                    Console.WriteLine(item.BlogName);
                }
            }
            Console.ReadKey();
        }
    }

F5,调试:

可以正常执行(上面那个小蝶惊鸿是上回合CodeFirst操作中遗留下来的数据)

 

3、EF工具帮我们生成了什么

上一节我们是一个快速入门,这一节我们看看EF Tool帮我们生成了些什么代码。

先看一下App.config

App.config
复制代码
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="CodeFirst_2013_3_23BlogContextContext" connectionString="Data Source=(localdb)\mydb;Initial Catalog=CodeFirst_2013_3_23.BlogContext;Integrated Security=True;MultipleActiveResultSets=True"
      providerName="System.Data.SqlClient" />
  </connectionStrings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>
</configuration>
复制代码
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

系统帮我们自动的填写配置信息,值得注意的是“connectionStrings”节点,这里配置了EF的连接字串,在初始化上下文的对象时,上下文的构造函数会默认的传入这里的连接字串。 

<connectionStrings>
    <add name="CodeFirst_2013_3_23BlogContextContext" connectionString="Data Source=(localdb)\mydb;Initial Catalog=CodeFirst_2013_3_23.BlogContext;Integrated Security=True;MultipleActiveResultSets=True"
      providerName="System.Data.SqlClient" />
  </connectionStrings>

进入“Model”文件夹

这里生成了一些实体类文件:

Post实体: 

Post
复制代码
    public partial class Post
    {
        public int PostID { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public int BlogID { get; set; }
        public virtual Blog Blog { get; set; }
    }
复制代码
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

 Blog实体: 

Blog
复制代码
    public partial class Blog
    {
        public Blog()
        {
            this.Posts = new List<Post>();
        }

        public int BlogID { get; set; }
        public string BlogName { get; set; }
        public string Url { get; set; }
        public virtual ICollection<Post> Posts { get; set; }
    }
复制代码
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

Type实体: 

Type
复制代码
    public partial class Type
    {
        public int TypeID { get; set; }
        public string TypeName { get; set; }
    }
复制代码
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

 User实体: 

User
复制代码
    public partial class User
    {
        public string UserName { get; set; }
        public string Display_Name { get; set; }
    }
复制代码
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

 还有上下文类CodeFirst_2013_3_23BlogContextContext: 

CodeFirst_2013_3_23BlogContextContext
复制代码
public partial class CodeFirst_2013_3_23BlogContextContext : DbContext
    {
        static CodeFirst_2013_3_23BlogContextContext()
        {
            Database.SetInitializer<CodeFirst_2013_3_23BlogContextContext>(null);
        }

        public CodeFirst_2013_3_23BlogContextContext()
            : base("Name=CodeFirst_2013_3_23BlogContextContext")
        {
        }

        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }
        public DbSet<Type> Types { get; set; }
        public DbSet<User> Users { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new BlogMap());
            modelBuilder.Configurations.Add(new PostMap());
            modelBuilder.Configurations.Add(new TypeMap());
            modelBuilder.Configurations.Add(new UserMap());
        }
    }
复制代码
按 Ctrl+C 复制代码
按 Ctrl+C 复制代码

 该上下文构造方法调用了父类DbContext的构造方法,传入配置文件中的数据库连接字串来连接需要的数据库。

(反编译DbContext得知其构造方法实际上是重载的方法,我们可以传入多种的参数形式,这里我们不做过多的介绍)

最后,我们进入“Mapping”文件夹

里面包含的都是实体与数据库,属性与字段映射的关系文件,作用跟使用edmx文件时,那繁琐的XML映射作用是一样的,不过,采用CodeFirst方式生成的关系映射,代码都是C#语言的,并且看起来相当清晰,以后重构起来也比edmx的XML方便得多。


至此,本回合的CodeFirst to Existing Database已经讨论讲解完毕,个人能力有限,可能文中会有错漏的地方,欢迎各位朋友指正以及提出建议。

  [ Entity FrameWork ]   [ Code First ]
知识共享许可协议 本作品由小蝶惊鸿创作,采用知识共享署名 4.0 国际许可协议进行许可,转载时请保留本文署名及链接。