原文地址:http://www.cnblogs.com/kenshincui/archive/2013/08/29/3290527.html

在前面的文章中我们提到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 Power Tools Beta 3下载安装包进行安装。

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

注意:如果使用“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中新增的“Hierarchyid”数据类型,目前只有先不用该类型的数据了,暂时将它改为其他类型。

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

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

<?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=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="AdventureWorksContext" connectionString="Data Source=.\SQL2008;Initial Catalog=AdventureWorks;Persist Security Info=True;User ID=sa;Password=123;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>

与此同时,对生成的数据库上下文操作类“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<AdventureWorksContext>(null);
} public AdventureWorksContext()
: base("Name=AdventureWorksContext")
{
} public DbSet<AWBuildVersion> AWBuildVersions { get; set; }
public DbSet<DatabaseLog> DatabaseLogs { get; set; }
public DbSet<ErrorLog> ErrorLogs { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<Department> Departments { get; set; }
public DbSet<Employee> Employees { get; set; }
public DbSet<EmployeeDepartmentHistory> EmployeeDepartmentHistories { get; set; }
public DbSet<EmployeePayHistory> EmployeePayHistories { get; set; }
public DbSet<JobCandidate> JobCandidates { get; set; }
public DbSet<Shift> Shifts { get; set; }
public DbSet<Address> Addresses { get; set; }
public DbSet<AddressType> AddressTypes { get; set; }
public DbSet<BusinessEntity> BusinessEntities { get; set; }
public DbSet<BusinessEntityAddress> BusinessEntityAddresses { get; set; }
public DbSet<BusinessEntityContact> BusinessEntityContacts { get; set; }
public DbSet<ContactType> ContactTypes { get; set; }
public DbSet<CountryRegion> CountryRegions { get; set; }
public DbSet<EmailAddress> EmailAddresses { get; set; }
public DbSet<Password> Passwords { get; set; }
public DbSet<Person> People { get; set; }
public DbSet<PersonPhone> PersonPhones { get; set; }
public DbSet<PhoneNumberType> PhoneNumberTypes { get; set; }
public DbSet<StateProvince> StateProvinces { get; set; }
public DbSet<BillOfMaterial> BillOfMaterials { get; set; }
public DbSet<Culture> Cultures { get; set; }
public DbSet<Illustration> Illustrations { get; set; }
public DbSet<Location> Locations { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<ProductCategory> ProductCategories { get; set; }
public DbSet<ProductCostHistory> ProductCostHistories { get; set; }
public DbSet<ProductDescription> ProductDescriptions { get; set; }
public DbSet<ProductInventory> ProductInventories { get; set; }
public DbSet<ProductListPriceHistory> ProductListPriceHistories { get; set; }
public DbSet<ProductModel> ProductModels { get; set; }
public DbSet<ProductModelIllustration> ProductModelIllustrations { get; set; }
public DbSet<ProductModelProductDescriptionCulture> ProductModelProductDescriptionCultures { get; set; }
public DbSet<ProductPhoto> ProductPhotoes { get; set; }
public DbSet<ProductProductPhoto> ProductProductPhotoes { get; set; }
public DbSet<ProductReview> ProductReviews { get; set; }
public DbSet<ProductSubcategory> ProductSubcategories { get; set; }
public DbSet<ScrapReason> ScrapReasons { get; set; }
public DbSet<TransactionHistory> TransactionHistories { get; set; }
public DbSet<TransactionHistoryArchive> TransactionHistoryArchives { get; set; }
public DbSet<UnitMeasure> UnitMeasures { get; set; }
public DbSet<WorkOrder> WorkOrders { get; set; }
public DbSet<WorkOrderRouting> WorkOrderRoutings { get; set; }
public DbSet<ProductVendor> ProductVendors { get; set; }
public DbSet<PurchaseOrderDetail> PurchaseOrderDetails { get; set; }
public DbSet<PurchaseOrderHeader> PurchaseOrderHeaders { get; set; }
public DbSet<ShipMethod> ShipMethods { get; set; }
public DbSet<Vendor> Vendors { get; set; }
public DbSet<CountryRegionCurrency> CountryRegionCurrencies { get; set; }
public DbSet<CreditCard> CreditCards { get; set; }
public DbSet<Currency> Currencies { get; set; }
public DbSet<CurrencyRate> CurrencyRates { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<PersonCreditCard> PersonCreditCards { get; set; }
public DbSet<SalesOrderDetail> SalesOrderDetails { get; set; }
public DbSet<SalesOrderHeader> SalesOrderHeaders { get; set; }
public DbSet<SalesOrderHeaderSalesReason> SalesOrderHeaderSalesReasons { get; set; }
public DbSet<SalesPerson> SalesPersons { get; set; }
public DbSet<SalesPersonQuotaHistory> SalesPersonQuotaHistories { get; set; }
public DbSet<SalesReason> SalesReasons { get; set; }
public DbSet<SalesTaxRate> SalesTaxRates { get; set; }
public DbSet<SalesTerritory> SalesTerritories { get; set; }
public DbSet<SalesTerritoryHistory> SalesTerritoryHistories { get; set; }
public DbSet<ShoppingCartItem> ShoppingCartItems { get; set; }
public DbSet<SpecialOffer> SpecialOffers { get; set; }
public DbSet<SpecialOfferProduct> SpecialOfferProducts { get; set; }
public DbSet<Store> Stores { get; set; }
public DbSet<vEmployee> vEmployees { get; set; }
public DbSet<vEmployeeDepartment> vEmployeeDepartments { get; set; }
public DbSet<vEmployeeDepartmentHistory> vEmployeeDepartmentHistories { get; set; }
public DbSet<vJobCandidate> vJobCandidates { get; set; }
public DbSet<vJobCandidateEducation> vJobCandidateEducations { get; set; }
public DbSet<vJobCandidateEmployment> vJobCandidateEmployments { get; set; }
public DbSet<vAdditionalContactInfo> vAdditionalContactInfoes { get; set; }
public DbSet<vStateProvinceCountryRegion> vStateProvinceCountryRegions { get; set; }
public DbSet<vProductAndDescription> vProductAndDescriptions { get; set; }
public DbSet<vProductModelCatalogDescription> vProductModelCatalogDescriptions { get; set; }
public DbSet<vProductModelInstruction> vProductModelInstructions { get; set; }
public DbSet<vVendorWithAddress> vVendorWithAddresses { get; set; }
public DbSet<vVendorWithContact> vVendorWithContacts { get; set; }
public DbSet<vIndividualCustomer> vIndividualCustomers { get; set; }
public DbSet<vPersonDemographic> vPersonDemographics { get; set; }
public DbSet<vSalesPerson> vSalesPersons { get; set; }
public DbSet<vSalesPersonSalesByFiscalYear> vSalesPersonSalesByFiscalYears { get; set; }
public DbSet<vStoreWithAddress> vStoreWithAddresses { get; set; }
public DbSet<vStoreWithContact> vStoreWithContacts { get; set; }
public DbSet<vStoreWithDemographic> 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模板引擎的朋友可以点击这里Lowering the Barriers to Code Generation with 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定义配置类来进行更多的映射控制请关注后面的文章。

(转)Entity Framework 5.0系列之自动生成Code First代码的更多相关文章

  1. Entity Framework 5.0系列之自动生成Code First代码

    在前面的文章中我们提到Entity Framework的"Code First"模式也同样可以基于现有数据库进行开发.今天就让我们一起看一下使用Entity Framework P ...

  2. 【转】Entity Framework 5.0系列之自动生成Code First代码

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

  3. Entity Framework 5.0系列之Code First数据库迁移

    我们知道无论是"Database First"还是"Model First"当模型发生改变了都可以通过Visual Studio设计视图进行更新,那么对于Cod ...

  4. 自动生成Code First代码

    自动生成Code First代码 在前面的文章中我们提到Entity Framework的“Code First”模式也同样可以基于现有数据库进行开发.今天就让我们一起看一下使用Entity Fram ...

  5. Entity Framework 5.0系列之数据操作

    Entity Framework将概念模型中定义的实体和关系映射到数据源,利用实体框架可以将数据源返回的数据具体化为对象:跟踪对象所做的更改:并发处理:将对象更改传播到数据源等.今天我们就一起讨论如何 ...

  6. Entity Framework 5.0系列之EF概览

    概述 在开发面向数据的软件时我们常常为了解决业务问题实体.关系和逻辑构建模型而费尽心机,ORM的产生为我们提供了一种优雅的解决方案.ADO.NET Entity Framework是.NET开发中一种 ...

  7. Entity Framework 5.0系列之EF概览-三种编程方式

    概述 在开发面向数据的软件时我们常常为了解决业务问题实体.关系和逻辑构建模型而费尽心机,ORM的产生为我们提供了一种优雅的解决方案.ADO.NET Entity Framework是.NET开发中一种 ...

  8. Entity Framework 5.0系列之约定配置

    Code First之所以能够让开发人员以一种更加高效.灵活的方式进行数据操作有一个重要的原因在于它的约定配置.现在软件开发越来复杂,大家也都试图将软件设计的越来越灵活,很多内容我们都希望是可配置的, ...

  9. 【转】Entity Framework 5.0系列之约定配置

    Code First之所以能够让开发人员以一种更加高效.灵活的方式进行数据操作有一个重要的原因在于它的约定配置.现在软件开发越来复杂,大家也都试图将软件设计的越来越灵活,很多内容我们都希望是可配置的, ...

随机推荐

  1. 12C中Profile的使用

    12c中PROFILE在PDB和CDB中是公用的,不过创建的profile名称在CDB和PDB有所不同. 如: 1.CDB中创建Profile SQL> show con_name CON_NA ...

  2. cpu 核数及逻辑数统计

    查看逻辑CPU个数:cat /proc/cpuinfo |grep "processor"|sort -u|wc -l24 查看物理CPU个数:grep "physica ...

  3. C# 动态加载WebService

    项目中需要用到WebService的方式来进行两个服务之间的方法调用,之前都是在项目中添加服务引用的方式来实现,但是这种方式有一个弊端,就是如果提供WebService服务的一方的IP.端口一旦变更, ...

  4. (转)pipe row的用法, Oracle split 函数写法.

    本文转载自:http://www.cnblogs.com/newsea/archive/2010/12/14/1905482.html 关于 pipe row的用法2009/12/30 14:53 = ...

  5. Oracle10g客户端连接远程数据库配置图解

    yuanwen:http://blog.csdn.net/DKZhu/article/details/6027933 一.      安装oracle客户端 1. 运行setup.exe,出现 2. ...

  6. 固态硬盘安装win7系统问题。

    可能出现:安装程序无法创建新的系统分区 出现这个错误后, 1.可以先尝试把固态硬盘插在硬盘的第一个硬盘口上,然后安装系统时拔掉U盘刷新再点击安装. 2.可以尝试在PE下直接安装系统. 如果上两个方法都 ...

  7. C Primer Plus学习笔记(十三)- 结构和其他数据形式

    建立结构声明 结构声明(structure declaration)描述了一个结构的组织布局 struct book { char title[MAXTITL]; char author[MAXAUT ...

  8. Flask之测试与部署

    5.1 蓝图Blueprint 为什么学习蓝图? 我们学习Flask框架,是从写单个文件,执行hello world开始的.我们在这单个文件中可以定义路由.视图函数.定义模型等等.但这显然存在一个问题 ...

  9. http://www.jb51.net/list/list_233_2.htm(导航: 首页 >> 软件编程 >> Android)

      日期:2015-04-24理解Android中Activity的方法回调 日期:2015-04-24Android获取手机通讯录.sim卡联系人及调用拨号界面方法 日期:2015-04-24And ...

  10. 带你剖析WebGis的世界奥秘----点和线的世界(转)

    带你剖析WebGis的世界奥秘----点和线的世界 转:https://zxhtom.oschina.io/zxh/20160813.html  编程  java  2016/08/13 0留言, 0 ...