博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Entity Framework 5.0系列之自动生成Code First代码
阅读量:5813 次
发布时间:2019-06-18

本文共 14526 字,大约阅读时间需要 48 分钟。

在前面的文章中我们提到Entity Framework的“Code First”模式也同样可以基于现有数据库进行开发。今天就让我们一起看一下使用Entity Framework Power Tools如何基于现有数据库生成数据类和数据库上下等。

Entity Framework Power Tools

基于现有数据库生成POCO数据类和数据库上下文需要借助Visual Studio一个扩展插件-- Entity Framework Power Tools(一个Code First反向工程工具)。只要在Visual Studio扩展里面输入“Entity Framework Power”搜索即可找到最新的扩展,点击下载即可(如下图)。当然你也可以到这里下载安装包进行安装。

安装完之后只要在项目上右键选择Entity Framework->Reverse Engineer Code First(项目中首先需要安装Entity Framework 包,否则会有错误),然后在弹出的窗口中输入相关的数据库连接信息即可(我们这里使用“AdventureWorks”数据库)。

note

注意:如果使用“AdventureWorks”数据库,可能发生如下错误:

One or more errors occurred while loading schema information.

error 6004: The table 'AdventureWorks.Production.Document' is referenced by a relationship, but cannot be found.

这是由于EF目前还不支持SQL Server 2008中新增的“”数据类型,目前只有先不用该类型的数据了,暂时将它改为其他类型。

然后我们稍等片刻,可以看到Entity Framework Power Tools已经根据所选数据库自动为你生成了数据类、数据库上下文操作类、对应的映射配置类并添加了数据库连接配置。

我们先看一下配置文件,可以看到在配置文件中Entity Framework Power Tools已经自动对数据库连接串进行了配置,添加了名为“AdventureWorksContext”的数据库连接串:

与此同时,对生成的数据库上下文操作类“AdventureWorksContext”进行了配置,在构造函数中使用了上面配置的“AdventureWorksContext”数据库连接:

using System.Data.Entity;using System.Data.Entity.Infrastructure;using EFPowerTools.Models.Mapping;namespace EFPowerTools.Models{    public partial class AdventureWorksContext : DbContext    {        static AdventureWorksContext()        {            Database.SetInitializer
(null); } public AdventureWorksContext() : base("Name=AdventureWorksContext") { } public DbSet
AWBuildVersions { get; set; } public DbSet
DatabaseLogs { get; set; } public DbSet
ErrorLogs { get; set; } public DbSet
OrderDetails { get; set; } public DbSet
Orders { get; set; } public DbSet
Departments { get; set; } public DbSet
Employees { get; set; } public DbSet
EmployeeDepartmentHistories { get; set; } public DbSet
EmployeePayHistories { get; set; } public DbSet
JobCandidates { get; set; } public DbSet
Shifts { get; set; } public DbSet
Addresses { get; set; } public DbSet
AddressTypes { get; set; } public DbSet
BusinessEntities { get; set; } public DbSet
BusinessEntityAddresses { get; set; } public DbSet
BusinessEntityContacts { get; set; } public DbSet
ContactTypes { get; set; } public DbSet
CountryRegions { get; set; } public DbSet
EmailAddresses { get; set; } public DbSet
Passwords { get; set; } public DbSet
People { get; set; } public DbSet
PersonPhones { get; set; } public DbSet
PhoneNumberTypes { get; set; } public DbSet
StateProvinces { get; set; } public DbSet
BillOfMaterials { get; set; } public DbSet
Cultures { get; set; } public DbSet
Illustrations { get; set; } public DbSet
Locations { get; set; } public DbSet
Products { get; set; } public DbSet
ProductCategories { get; set; } public DbSet
ProductCostHistories { get; set; } public DbSet
ProductDescriptions { get; set; } public DbSet
ProductInventories { get; set; } public DbSet
ProductListPriceHistories { get; set; } public DbSet
ProductModels { get; set; } public DbSet
ProductModelIllustrations { get; set; } public DbSet
ProductModelProductDescriptionCultures { get; set; } public DbSet
ProductPhotoes { get; set; } public DbSet
ProductProductPhotoes { get; set; } public DbSet
ProductReviews { get; set; } public DbSet
ProductSubcategories { get; set; } public DbSet
ScrapReasons { get; set; } public DbSet
TransactionHistories { get; set; } public DbSet
TransactionHistoryArchives { get; set; } public DbSet
UnitMeasures { get; set; } public DbSet
WorkOrders { get; set; } public DbSet
WorkOrderRoutings { get; set; } public DbSet
ProductVendors { get; set; } public DbSet
PurchaseOrderDetails { get; set; } public DbSet
PurchaseOrderHeaders { get; set; } public DbSet
ShipMethods { get; set; } public DbSet
Vendors { get; set; } public DbSet
CountryRegionCurrencies { get; set; } public DbSet
CreditCards { get; set; } public DbSet
Currencies { get; set; } public DbSet
CurrencyRates { get; set; } public DbSet
Customers { get; set; } public DbSet
PersonCreditCards { get; set; } public DbSet
SalesOrderDetails { get; set; } public DbSet
SalesOrderHeaders { get; set; } public DbSet
SalesOrderHeaderSalesReasons { get; set; } public DbSet
SalesPersons { get; set; } public DbSet
SalesPersonQuotaHistories { get; set; } public DbSet
SalesReasons { get; set; } public DbSet
SalesTaxRates { get; set; } public DbSet
SalesTerritories { get; set; } public DbSet
SalesTerritoryHistories { get; set; } public DbSet
ShoppingCartItems { get; set; } public DbSet
SpecialOffers { get; set; } public DbSet
SpecialOfferProducts { get; set; } public DbSet
Stores { get; set; } public DbSet
vEmployees { get; set; } public DbSet
vEmployeeDepartments { get; set; } public DbSet
vEmployeeDepartmentHistories { get; set; } public DbSet
vJobCandidates { get; set; } public DbSet
vJobCandidateEducations { get; set; } public DbSet
vJobCandidateEmployments { get; set; } public DbSet
vAdditionalContactInfoes { get; set; } public DbSet
vStateProvinceCountryRegions { get; set; } public DbSet
vProductAndDescriptions { get; set; } public DbSet
vProductModelCatalogDescriptions { get; set; } public DbSet
vProductModelInstructions { get; set; } public DbSet
vVendorWithAddresses { get; set; } public DbSet
vVendorWithContacts { get; set; } public DbSet
vIndividualCustomers { get; set; } public DbSet
vPersonDemographics { get; set; } public DbSet
vSalesPersons { get; set; } public DbSet
vSalesPersonSalesByFiscalYears { get; set; } public DbSet
vStoreWithAddresses { get; set; } public DbSet
vStoreWithContacts { get; set; } public DbSet
vStoreWithDemographics { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new AWBuildVersionMap()); modelBuilder.Configurations.Add(new DatabaseLogMap()); modelBuilder.Configurations.Add(new ErrorLogMap()); modelBuilder.Configurations.Add(new OrderDetailMap()); modelBuilder.Configurations.Add(new OrderMap()); modelBuilder.Configurations.Add(new DepartmentMap()); modelBuilder.Configurations.Add(new EmployeeMap()); modelBuilder.Configurations.Add(new EmployeeDepartmentHistoryMap()); modelBuilder.Configurations.Add(new EmployeePayHistoryMap()); modelBuilder.Configurations.Add(new JobCandidateMap()); modelBuilder.Configurations.Add(new ShiftMap()); modelBuilder.Configurations.Add(new AddressMap()); modelBuilder.Configurations.Add(new AddressTypeMap()); modelBuilder.Configurations.Add(new BusinessEntityMap()); modelBuilder.Configurations.Add(new BusinessEntityAddressMap()); modelBuilder.Configurations.Add(new BusinessEntityContactMap()); modelBuilder.Configurations.Add(new ContactTypeMap()); modelBuilder.Configurations.Add(new CountryRegionMap()); modelBuilder.Configurations.Add(new EmailAddressMap()); modelBuilder.Configurations.Add(new PasswordMap()); modelBuilder.Configurations.Add(new PersonMap()); modelBuilder.Configurations.Add(new PersonPhoneMap()); modelBuilder.Configurations.Add(new PhoneNumberTypeMap()); modelBuilder.Configurations.Add(new StateProvinceMap()); modelBuilder.Configurations.Add(new BillOfMaterialMap()); modelBuilder.Configurations.Add(new CultureMap()); modelBuilder.Configurations.Add(new IllustrationMap()); modelBuilder.Configurations.Add(new LocationMap()); modelBuilder.Configurations.Add(new ProductMap()); modelBuilder.Configurations.Add(new ProductCategoryMap()); modelBuilder.Configurations.Add(new ProductCostHistoryMap()); modelBuilder.Configurations.Add(new ProductDescriptionMap()); modelBuilder.Configurations.Add(new ProductInventoryMap()); modelBuilder.Configurations.Add(new ProductListPriceHistoryMap()); modelBuilder.Configurations.Add(new ProductModelMap()); modelBuilder.Configurations.Add(new ProductModelIllustrationMap()); modelBuilder.Configurations.Add(new ProductModelProductDescriptionCultureMap()); modelBuilder.Configurations.Add(new ProductPhotoMap()); modelBuilder.Configurations.Add(new ProductProductPhotoMap()); modelBuilder.Configurations.Add(new ProductReviewMap()); modelBuilder.Configurations.Add(new ProductSubcategoryMap()); modelBuilder.Configurations.Add(new ScrapReasonMap()); modelBuilder.Configurations.Add(new TransactionHistoryMap()); modelBuilder.Configurations.Add(new TransactionHistoryArchiveMap()); modelBuilder.Configurations.Add(new UnitMeasureMap()); modelBuilder.Configurations.Add(new WorkOrderMap()); modelBuilder.Configurations.Add(new WorkOrderRoutingMap()); modelBuilder.Configurations.Add(new ProductVendorMap()); modelBuilder.Configurations.Add(new PurchaseOrderDetailMap()); modelBuilder.Configurations.Add(new PurchaseOrderHeaderMap()); modelBuilder.Configurations.Add(new ShipMethodMap()); modelBuilder.Configurations.Add(new VendorMap()); modelBuilder.Configurations.Add(new CountryRegionCurrencyMap()); modelBuilder.Configurations.Add(new CreditCardMap()); modelBuilder.Configurations.Add(new CurrencyMap()); modelBuilder.Configurations.Add(new CurrencyRateMap()); modelBuilder.Configurations.Add(new CustomerMap()); modelBuilder.Configurations.Add(new PersonCreditCardMap()); modelBuilder.Configurations.Add(new SalesOrderDetailMap()); modelBuilder.Configurations.Add(new SalesOrderHeaderMap()); modelBuilder.Configurations.Add(new SalesOrderHeaderSalesReasonMap()); modelBuilder.Configurations.Add(new SalesPersonMap()); modelBuilder.Configurations.Add(new SalesPersonQuotaHistoryMap()); modelBuilder.Configurations.Add(new SalesReasonMap()); modelBuilder.Configurations.Add(new SalesTaxRateMap()); modelBuilder.Configurations.Add(new SalesTerritoryMap()); modelBuilder.Configurations.Add(new SalesTerritoryHistoryMap()); modelBuilder.Configurations.Add(new ShoppingCartItemMap()); modelBuilder.Configurations.Add(new SpecialOfferMap()); modelBuilder.Configurations.Add(new SpecialOfferProductMap()); modelBuilder.Configurations.Add(new StoreMap()); modelBuilder.Configurations.Add(new vEmployeeMap()); modelBuilder.Configurations.Add(new vEmployeeDepartmentMap()); modelBuilder.Configurations.Add(new vEmployeeDepartmentHistoryMap()); modelBuilder.Configurations.Add(new vJobCandidateMap()); modelBuilder.Configurations.Add(new vJobCandidateEducationMap()); modelBuilder.Configurations.Add(new vJobCandidateEmploymentMap()); modelBuilder.Configurations.Add(new vAdditionalContactInfoMap()); modelBuilder.Configurations.Add(new vStateProvinceCountryRegionMap()); modelBuilder.Configurations.Add(new vProductAndDescriptionMap()); modelBuilder.Configurations.Add(new vProductModelCatalogDescriptionMap()); modelBuilder.Configurations.Add(new vProductModelInstructionMap()); modelBuilder.Configurations.Add(new vVendorWithAddressMap()); modelBuilder.Configurations.Add(new vVendorWithContactMap()); modelBuilder.Configurations.Add(new vIndividualCustomerMap()); modelBuilder.Configurations.Add(new vPersonDemographicMap()); modelBuilder.Configurations.Add(new vSalesPersonMap()); modelBuilder.Configurations.Add(new vSalesPersonSalesByFiscalYearMap()); modelBuilder.Configurations.Add(new vStoreWithAddressMap()); modelBuilder.Configurations.Add(new vStoreWithContactMap()); modelBuilder.Configurations.Add(new vStoreWithDemographicMap()); } }}

 

在项目中我们还可以看到Entity Framework Power Tools自动创建了一个Models文件夹,这里除了“AdventureWorksContext”类还有所有的数据类。在Models文件夹下还有一个“Mapping”文件夹,这里放了数据类与数据库的映射配置类,可以看出Entity Framework Power Tools通过fluent API的方式进行映射细节配置(目前Entity Framework Power Tools还不支持Data Annotations方式),关于配置类的具体细节我们这里暂不进行详细介绍。

下面我们进行数据查询:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using EFPowerTools.Models;namespace EFPowerTools{    class Program    {        static void Main(string[] args)        {            using (var db = new AdventureWorksContext())            {                var persons = db.People.Where(p => p.LastName == "Stevens").OrderBy(p=>p.FirstName);                foreach(var p in persons)                {                    Console.WriteLine("FirstName:{0},LastName:{1}", p.FirstName, p.LastName);                }            }        }    }}

查询结果:

自定义模板

事实上Entity Framework Power Tools的功能还远不止这些,例如我们上面谈到Entity Framework Power Tools使用fluent API进行映射配置,而通常情况下开发人员更喜欢使用Data Annotations方式进行映射约定,那么此时你就可以选择配置自己的模板。

在项目上右键选择Entity Frmaework->Customize Reverse Engineer Templates,此时会看到项目中添加了一个“CodeTemplates”文件夹,里面存放了Entity Framework Power Tools用于生产相关类文件的T4模板(对于不了解T4模板引擎的朋友可以点击这里),如果此时再使用Entity Framework Power Tools进行Code First反向工程操作将使用当前这个文件夹中的模板进行生成。接下来看一下如何进行模板自定义。

首先让我们打开Mapping.tt文件,这个文件主要用户生成配置类,在Entity Framework Power Tools默认生成的代码中通过fluent API进行表名和数据类名以及属性名同列名的对应配置,例如下面的代码:

下面让我们修改一下Mapping.tt文件,去掉上面的约束,而改用Data Annotations方式进行约定。首先去掉下图中选择的代码,此时生成的映射类中就不再出现上图中选择的代码部分:

然后我们需要修改Entity.tt模板,将数据库中的表和列的映射声明到数据类上。先让我们将数据类和表做对应,这需要在数据类上添加“Table”声明,标记出表名和架构名(EF默认会使用dbo架构),在如图位置添加如下代码:

<#         var tableName = (string)efHost.TableSet.MetadataProperties["Table"].Value ?? efHost.TableSet.Name;         var conventionTableName = System.Data.Entity.Design.PluralizationServices.PluralizationService                 .CreateService(new CultureInfo("en"))                 .Pluralize(efHost.EntityType.Name);        var schemaName = (string)efHost.TableSet.MetadataProperties["Schema"].Value;         schemaName = string.IsNullOrWhiteSpace(schemaName)                 ? "dbo"                 : schemaName;        if(schemaName != "dbo" || conventionTableName != tableName)         { #>     [Table("<#= tableName #>", Schema="<#= schemaName #>")] <#         }#>

这段代码主要处理逻辑是:当架构不是“dbo”或者表名的复数形式同表名不同时添加“Table”标记声明。之所以添加判断是因为EF的默认使用“dbo”架构并且EF在操作表的时候默认将数据类的复数形式作为表名。

接下来添加列标记声明,在如图位置添加如下代码即可:

var columnName = efHost.PropertyToColumnMappings[property].Name;                 if(code.Escape(property) != columnName)                 { #>         [Column("<#= columnName #>")] <#                 }

这里只是简单的对列名和编码后的列名进行比较,不同则添加列标记,否则不添加(EF默认认为数据类属性名和表的列名相同)。

由于刚才添加的标记属性类在“System.ComponentModel.DataAnnotations.Schema” 命名空间下,因此最后还需要在模板头部添加该命名空间:

 

<#        if (efHost.EntityFrameworkVersion >= new Version(4, 4))         { #> using System.ComponentModel.DataAnnotations.Schema; <#         }         else         { #> using System.ComponentModel.DataAnnotations; <#         } #>

由于之前的EF版本中“Table”和“Column”类不在“System.ComponentModel.DataAnnotations.Schema”命名空间而是在 “System.ComponentModel.DataAnnotations”命名空间中,因此这里我们还需要添加一个判断。

今天的内容先到此为止,关于如何使用fluent API及Data Annotations定义配置类来进行更多的映射控制请关注后面的文章。

转载地址:http://wytbx.baihongyu.com/

你可能感兴趣的文章
在 Unix 系统上查找数据的最佳工具和技巧
查看>>
《Python参考手册(第4版•修订版)》——2.4 字符串字面量
查看>>
《量化金融R语言高级教程》一2.4 参考文献
查看>>
ProxyChains
查看>>
zabbix集成zatree和onealert告警安装
查看>>
java中Integer和int
查看>>
敏捷团队:我尽力先做好本职工作是否正确?
查看>>
LGPL 协议详解
查看>>
VTK读取raw格式的数据
查看>>
自我学习-多线程基础篇1
查看>>
Xamarin大学研讨会记录|使用Visual Studio的Xamarin来构建第一个Android应用
查看>>
CentOS系统初装后的优化
查看>>
hyper-v的备份和恢复
查看>>
问题不要再留给明天
查看>>
maven 插件
查看>>
eclipse创建项目
查看>>
4、Go HTTP框架Beego - 快速入门
查看>>
意义生活!
查看>>
[问题解决] Python实现final这个功能
查看>>
java泛型
查看>>