在Entity Framework Model First下, 一个非常常见的需求是改变数据库脚本的生成方式。这个应用场景是指,当用户在Designer上单击鼠标右键,然后选择Generate Database from Model选项,此时Entity Framework Model First会根据模型产生数据库SQL脚本,并将SQL脚本文件添加到解决方案资源管理器中。

事实上,这个自动化产生的数据库SQL脚本还是会有一些局限性。比如:Model上支持DateTime这一CLR类型,在自动化SQL生成的过程中,Entity Framework会自动使用SQL中的数据类型datetime来产生相应的字段定义,如果我们希望对于某些DateTime类型的属性产生date类型,而不是datetime类型的字段,那么我们就需要对数据库脚本的生成方式做一些修改。

例子

首先看一个例子,我们建立一个非常简单的模型:Employee,在这个Employee实体中会有一个DayOfBirth的属性,用以保存雇员的生日日期。该模型定义如下:

在模型设计器上单击鼠标右键,选择“Generate Database from Model”菜单后,产生的SQL语句如下,可以看到,对于DayOfBirth属性,产生的字段是datetime类型:

现在,让我们来尝试改变Entity Framework Model First下数据库SQL脚本的生成方式,以使得所产生的DayOfBirth字段为date类型。

实现

通过使用Entity Framework的Structural Annotation的特性,我们可以很方便地定制SQL脚本的生成方式。

首先,在Solution Explorer中,找到模型文件(扩展名为edmx的文件),单击鼠标右键,选择Open With选项。在Open With对话框中,选择Automatic Editor Selector:

此时会关闭模型设计器,并以XML编辑器的方式打开edmx文件。在打开的编辑器中,我们可以看到edmx文件的详细内容。如果模型比较大的话,这个文件的内容也会比较多(有的甚至几千几万行)。总体来看,主要有三个部分:

  • SSDL content:对存储模型的定义
  • CSDL content:对概念模型的定义 - 也就是保存设计器上所设计的模型
  • C-S mapping content:定义了概念模型与存储模型之间的映射

一看就知道,Entity Framework就是一个ORM框架(废话)。

接下来,我们要对edmx的概念模型部分做一些修改。修改的目的就是为了给SQL脚本的自动化生成提供一些客户化的信息,以便自动化生成工具能够根据这些客户化信息产生不同的结果。

我们需要在ConceptualModels节点下的Schema上定义自己的命名空间。例如:

然后,我们自己自定义一个XML标签,并把这个标签应用到概念模型中的DayOfBirth属性上,如下:

注意此处的“edmx:CopyToSSDL”属性,意思是这部分属性需要在产生模型的时候复制到SSDL存储模型中。因为在生成SQL脚本时,转换引擎会读取SSDL中的内容并根据这些内容产生SQL。现在,我们双击edmx文件,并重新在设计器中打开模型。同样在设计器中点击鼠标右键,选择“Generate Database from Model”选项,待SQL脚本重新生成之后,再用XML编辑器打开edmx文件,此时我们会看到,在SSDL部分,先前添加的“custom:SqlType”节点也被复制到了这里,只不过稍许有些变化:

现在,我们需要定制SQL脚本的产生过程。打开模型设计器,在模型设计器的属性编辑窗口中,我们可以看到一个名为“DDL Generation Template”的属性:

它就是主导SQL脚本生成的T4模板文件,现在需要对这个T4文件进行定制。该文件位于%PROGRAMFILES(x86)%\Microsoft Visual Studio 12.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen目录下。为了不更改原有的SSDLToSQL10.tt文件,我们将其复制到Solution Explorer中,注意将该文件的BuildAction设置为None,并去掉Custom Tool的设置:

仍然打开模型设计器,在属性窗口中,设置“DDL Generation Template”属性为“.\SSDLToSQL10.tt”,注意路径符“.\”,它表示需要使用Solution Explorer下的SSDLToSQL10.tt文件,而不是标准的那个文件。

最关键的一步,就是修改SSDLToSQL10.tt文件。打开这个文件,找到“Creating all tables”部分,并用以下粉红色高亮部分替换其中的内容:

注意:我们还需要在这个tt文件的顶部引入System.XML和System.XML.Linq的命名空间:

<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq" #>
<#@ import namespace="System.Xml" #>
<#@ import namespace="System.Xml.Linq" #>

至此,实现部分已经完成。

测试

现在来测试一下效果。双击打开edmx模型,在模型设计器上单击鼠标右键,选择“Generate Database from Model”,然后查看生成的SQL语句。我们发现,DayOfBirth已经变成了date类型了:

如果在产生数据库脚本的时候提示以下错误,请稍许更改一下模型(比如拖动一下模型中的实体等)保存之后再试。

Entity Framework Model First下改变数据库脚本的生成方式的更多相关文章

  1. Entity Framework 之Database first(数据库优先)&Model First(模型优先)

    一.什么是Entity Framework 1.1 实体框架(EF)是一个对象关系映射器,使.NET开发人员使用特定于域的对象与关系数据.它消除了需要开发人员通常需要编写的大部分数据访问代码.简化了原 ...

  2. C# ORM—Entity Framework 之Database first(数据库优先)&Model First(模型优先)(一)

    一.什么是Entity Framework 1.1 实体框架(EF)是一个对象关系映射器,使.NET开发人员使用特定于域的对象与关系数据.它消除了需要开发人员通常需要编写的大部分数据访问代码.简化了原 ...

  3. [UWP小白日记-11]在UWP中使用Entity Framework Core(Entity Framework 7)操作SQLite数据库(一)

    前言 本文中,您将创建一个通用应用程序(UWP),使用Entity Framework Core(Entity Framework 7)框架在SQLite数据库上执行基本的数据访问. 准备: Enti ...

  4. Entity FrameWork 中使用Lambda访问数据库性能优化

    在使用Entity Framework 访问数据库时,我们经常使用Lambda表达式,但是如果不小心的话,很容易就掉到坑里了.比如下面的例子:用Lambda访问MSSqlServer中的NewsInf ...

  5. How to: Use the Entity Framework Model First in XAF 如何:在 XAF 中使用EF ModelFirst

    This topic demonstrates how to use the Model First entity model and a DbContext entity container in ...

  6. Entity Framework 在Vs2012下Update Model From DataBase 失败的问题

    http://stackoverflow.com/questions/13054212/vs-2012-ef-5-0-update-model-from-database-not-picking-up ...

  7. Entity FrameWork Code First 之 MVC4 数据库初始化策略用法

    通过启用迁移和更新数据库可以很容易的生成一张表.但是对数据库修改之后,通过数据迁移就没那么好实现了. 这里用到数据库生成策略,进行对数据库操作: 一.3种主要数据库生成策略 1 CreateDatab ...

  8. Entity FrameWork Code First无法生成数据库 解决办法

    我是控制台应用程序,没有connectionStrings,试了几个方法也都不可以. 这是别人的博客用其他方法. http://www.cnblogs.com/Gyoung/archive/2013/ ...

  9. Entity Framework EF6使用 MySql创建数据库异常解决办法

    EF6使用MySQL数据库时,第一次创建数据库出现“Specified key was too long; max key length is 767 bytes”错误,解决办法请见以下连接. htt ...

随机推荐

  1. NSIS 无边框移动问题总结笔记

    无边框移动 插件 WinProc WinCore.nsh [一定要有这个] 代码 ;事件 ;处理无边框移动 Function onGUICallback ${If} $MSG = ${WM_LBUTT ...

  2. 享元模式 - Flyweight

    Flyweight(享元模式) 定义 GOF:运用共享技术有效地支持大量细粒度的对象. GOF的定义比较专业化,通俗来说,当你有大量相似的实例时,你把其中相同的实例取出来共享. 例子 在你的游戏场景中 ...

  3. canvas初探2

    2.2 canvas的绘图环境 canvas仅仅只是一个绘图的容器,其内存在一个绘图环境,该环境对象提供了全部的绘图功能. 目前canvas的绘图环境是2d,但canvas规范在着手准备支持其他类型的 ...

  4. 学习笔记:delphi多线程知识

    最近一直在温习旧的知识,刚好学习了一下Java的线程安全方面的知识,今天想起之前一直做的Delphi开发,所以还是有必要温习一下,看看这些不同的编程语言有什么不同之处. Delphi的线程同步方法: ...

  5. SQL Server定时自动抓取耗时SQL并归档数据发邮件脚本分享

    SQL Server定时自动抓取耗时SQL并归档数据发邮件脚本分享 第一步建库和建表 USE [master] GO CREATE DATABASE [MonitorElapsedHighSQL] G ...

  6. ASP.NET vNext 概述

    兼容Mono的下一代云环境Web开发框架ASP.NET vNext 我们知道了ASP.NET vNext是一个全新的框架,是一个与时俱进的框架.这篇文章将深入讨论在整体架构更多的细节,文档参照 ASP ...

  7. 深入NSQ 之旅[转载]

    介绍 NSQ是一个实时的分布式消息平台.它的设计目标是为在多台计算机上运行的松散服务提供一个现代化的基础设施骨架.这篇文章介绍了 基于go语言的NSQ的内部架构,它能够为高吞吐量的网络服务器带来 性能 ...

  8. EF遇到的一些问题

    环境:EntityFramework 版本号:4.1.0.0 问题一:“数据读取器与指定的“.......”不兼容.某个类型为“...”的成员在同名的数据读取器中没有对应的列.”. 使用方式:rep. ...

  9. 你必须知道的指针基础-4.sizeof计算数组长度与strcpy的安全性问题

    一.使用sizeof计算数组长度 1.1 sizeof的基本使用 如果在作用域内,变量以数组形式声明,则可以使用sizeof求数组大小,下面一段代码展示了如何使用sizeof: ,,,,,}; int ...

  10. 作业三: 代码规范、代码复审、PSP

    分) 对于是否需要有代码规范,请考虑下列论点并反驳/支持: 这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 我是个艺术家,手艺人,我有自己的规范和原则. 规范不能 ...