随着.NET 4.0时代的到来,开发者愈来愈关注如何能加快开发效率,从而构建健壮的程序。而微软在.NET 4.0推出的Entity Framework,无疑是值得开发者去学习的,它其实是微软的ADO.NET的加强版本,是个ORM框架。在本文中,将以例子的形式简单介绍最新的 Entity Framework 4.1的基本用法。 html
介 绍 web
在旧的Entity 框架中,开发者能够从已存在的数据库中产生业务实体的模型,这种开发方法被称为数据库驱动的开发方法。而在4.1的Entity Framework中,支开发者先建立实体业务类,而后再产生相关的数据库文件,这种开发方法能够称为“代码先行”的开发方法。这种方法对于开发者来讲是 颇有好处的,首先,会让开发者从面向对象的思惟角度出发,去构建业务逻辑中的实体模型,而后再根据实际的须要去生成数据库文件,是真正的面向对象的思惟开 发方法。 数据库
本文中要使用Entity Framework 4.1,这里提供下载该框架安装程序:Entity Framework 4.1。 c#
同时,VS.NET 2010也是少不了的,而本文的配套代码,能够在这里下载:VS.NET 2010。 app
本文的例子将会建立两个类Invoice类和LineItem类。而本文产生的数据库命名为Accounting,并会产生两张表:Invoice和 LineItem。例子中的功能,还包括能够在gridview中对数据库中的数据进行增删改查,最后,还会演示若是类发生了变化了,如何让相应的数据库 也发生改变。 框架
步骤1 asp.net
1) 启动vs.net 2010; ide
2) 新创建一个c#语言的asp.net web工程项目; 函数
3) 将工程命名为project EF4CodeFirst; 工具
4) 在工程资源管理器中,鼠标右键点击,而后新增一个类,将新增的类命名为Invoice.cs。
修改这个类的代码以下:
publicclass Invoice { publicint ID { get; set; } public DateTime InvoiceDate { get; set; } publicdouble Total { get; set; } }
在咱们的类中,有id这个属性,Entity框架会根据id这个属性,去生成数据库表中的对应字段id,若是类中没定义id这个属性,则会在数据库表文件中生成以“类文件名+ID”这样命名的字段。
在这个Invoice发票类中,存在多个条目LineItem,它们之间明显构成一对多的关系,因此咱们先创建类LineItem类。
5) 一样,新增一个LineItem类,代码以下:
publicclass LineItem { publicint ID { get; set; } publicstring ProductName { get; set; } publicdouble ItemCost { get; set; } publicdouble Units { get; set; } public Invoice Invoice { get; set; } }
在这个类中,维持了对Invoice类的引用,同时也是关联了Invoice类。
6)而在Invoice类中,也要增长LineItem类的引用,这里要用到的是集合类,以下代码:
public ICollection<LineItem> LineItems { get; set; }
同时要在Invovice类的构造函数中,进行初始化LineItem类,以下:
public Invoice() { LineItems =new List<LineItem>(); }
在完成上面的步骤后,则Entity框架已能够从实体类中建立相关的数据库和表了,下面继续进行步骤二。
步骤2
接下来,咱们要引用Entity框架的类库文件到咱们的工程中。
1) 在工程资源管理器中,鼠标右键点击工程名字,在弹出的菜单中选择“添加引用”。
2) 在出现的以下图的界面中,选择System.Data.Entity ,并点肯定完成:
3) 为工程继续增长一个新类,命名为Accounting.cs ,而且修改其代码以下:
using System.Data.Entity; publicclass Accounting : DbContext { public Accounting() : base("Accounting") {} public override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); } public DbSet<Invoice> Invoices { get; set; } public DbSet<LineItem> LineItems { get; set; } }
能够看到,该类继承了DbContext类,该类其实是Entity的一个工具类,里面封装了不少有用的API,在Accounting类中,分别有两个DbSet类的实例,它们表明将要在数据库中生成的两个表。
构造函数继承了积累构造函数,并将名为 “Accounting” 的链接字符串做为参数,以使用该字符串。若是不写该构造函数,将自动使用与该DbContext同名的链接字符串,也就是 name="Accounting" 的连接字符串。
重写OnModelCreating方法,增长 modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 是为了在数据库中生成表时,表名以单数形式出现,不然数据库中表名为:Invoices,LineItems。
4)接着须要在web.config中进行添加数据库链接,以下:
<add name="Accounting"
providerName="System.Data.SqlClient"
connectionString="Data Source=(local);Initial Catalog=Accounting;Integrated Security=SSPI;"/>
5) 接着,在default.aspx 中添加gridview控件,而且编写以下代码:
using System.Data.Entity; protectedvoid Page_Load(object sender, EventArgs e) { Accounting db =new Accounting(); db.Invoices.Load(); GridView1.DataSource = db.Invoices.Local.ToBindingList(); GridView1.DataBind(); }
记得这里必须引入System.Data.Entity类库,而且实例化Accounting对象的实例db,并调用其load方法,加载全部的Invoice数据(这里咱们通常是加载一对多的一方的数据)。
6)运行工程后,你会发如今SQL SERVER中,会出现了三张表,以下图:
其中,分别是Invoice表和LineItem表,还有一张表EdmMetadata,是Entity框架为咱们自动生成的,保存了数据库中的元数据。另外,能够看到在表LineItem中,Entity框架已经为咱们自动生成了外键Invoice_ID,以下图:
步骤三
如今,既然数据库已经建立了,则能够为其增长一些数据了,在page_load中增长以下代码:
protectedvoid Page_Load(object sender, EventArgs e) { Accounting db =new Accounting(); Invoice invoice =new Invoice { InvoiceDate = DateTime.Now, Total =1000 }; db.Invoices.Add(invoice); db.SaveChanges(); db.Invoices.Load(); GridView1.DataSource = db.Invoices.Local.ToBindingList(); GridView1.DataBind(); }
在这里咱们实例化了Invoice类的一个实例,添加了相关的数据内容,而后使用db.Invoices.Add增长到Account类的DBSet属性中,最后调用savechanges方法保存到数据库中,运行后,能够看到以下效果:
如今咱们试下更新数据,代码以下:
protectedvoid Page_Load(object sender, EventArgs e) { Accounting db =new Accounting(); Invoice invoice =new Invoice { ID =1, InvoiceDate = DateTime.Now, Total =900 }; db.Entry(invoice).State = EntityState.Modified; db.SaveChanges(); db.Invoices.Load(); GridView1.DataSource = db.Invoices.Local.ToBindingList(); GridView1.DataBind(); }
这里把invoice实例的成员变量的ID改成1,注意在更新时,设置其状态(state)为EntityState.Modified,表示是修改记录,最后再保存,运行后,能够看到数据库中的数据的确更新了,全部这些都是Entity 框架在起做用。
最后学习删除记录,代码以下:
protectedvoid Page_Load(object sender, EventArgs e) { Accounting db =new Accounting(); Invoice invoice =new Invoice { ID =1, InvoiceDate = DateTime.Now, Total =900 }; db.Invoices.Remove(invoice); db.SaveChanges(); db.Invoices.Load(); GridView1.DataSource = db.Invoices.Local.ToBindingList(); GridView1.DataBind(); }
这里只须要调用Remove方法,便可在数据库中删除该记录。
步骤4
在这个步骤中,咱们学习如何改变数据模型。假设咱们要在Invoice类中增长一个Tax的属性,也须要Entity框架同步在数据库中增长这个字段,下面演示其步骤:
1)咱们在Invoice类中增长Tax这个属性。
2)若是这时运行工程,则会看到以下的错误提示:
The model backing the 'Accounting' context has changed since the database was
created. Either manually delete/update the database, or call
Database.SetInitializer with an IDatabaseInitializer instance. For example, the
DropCreateDatabaseIfModelChanges strategy will automatically delete and recreate
the database, and optionally seed it with new data.
提示告诉咱们,或者这个时候从新手工删除数据库或者使用代码的方法去完成,咱们使用代码的方法去完成,只须要在Application_Start事件中编码以下,便可让Entity框架,自动把新增长的属性反映到数据库中:
void Application_Start(object sender, EventArgs e) { // Code that runs on application startup System.Data.Entity.Database.SetInitializer<Accounting> (new System.Data.Entity.DropCreateDatabaseIfModelChanges<Accounting>()); }
3) 再次运行工程,会看到数据表中的确增长了Tax这个字段了,以下图:
步骤5
注意,在上面的步骤4中,若是类的属性发生变化,则实际上是经过代码的方法,从新将旧的数据库DROP掉,而后再新建,这样的话费时费力,而能够经过另外的一个方法实现,即还好咱们能够在初始化的过程当中添加测试数据,这样每次从新建立数据库的时候,测试数据就会自动加进去了,算是解决了一些问题,方法以下:
1)在工程项目中,新增长一个类,命名为AccountingInitializer.cs
2)修改其代码以下:
publicclass AccountingInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges<Accounting> { protectedoverridevoid Seed(Accounting context) { Invoice invoice =new Invoice { Total =20, InvoiceDate = new DateTime(2011, 4, 14), Tax =1.50 }; invoice.LineItems.Add(new LineItem { ItemCost =2, ProductName ="Test", Units =4 }); invoice.LineItems.Add(new LineItem { ItemCost =4, ProductName ="Test 2", Units =3 }); context.Invoices.Add(invoice); context.SaveChanges(); base.Seed(context); } }
其中,在这个类中继承了DropCreateDatabaseIfModelChanges这个类,而且重写了seed这个方法,在这个方法中能够编写新增测试数据。要记得还须要在Application_OnStart事件中编写以下代码:
void Application_Start(object sender, EventArgs e)
{
//在启动过程当中执行该段代码
System.Data.Entity.Database.SetInitializer<Accounting>
(new AccountingInitializer());
}
小 结
能够看到,Entity Framework 4.1的确方便了用户的开发操做,能让用户更专一于业务逻辑实体的开发,更符合OOP的思惟方式,更多关于Entity Framework的操做,请参考微软的MSDN