转:工欲善其事必先利其器—Entity Framework实例详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转:工欲善其事必先利其器—Entity Framework实例详解相关的知识,希望对你有一定的参考价值。
开始本篇文章之前,先说一下Entity Framework 6 Alpha1在NuGet中已可用,原文链接http://blogs.msdn.com/b/adonet/archive/2012/10/30/ef6-alpha-1-available-on-nuget.aspx
俗话说:“工欲善其事必先利其器”,在深入讲解Entity Framework之前,先准备一下开发工具以及前期的配置。
一、开发工具
开发工具基本略过,这里说一下,我使用的是Visual Studio 2012,Entity Framework版本为4.3.1,获取这个版本的办法:在Package Manager Console中输入Install-Package EntityFramework -Version 4.3.1。至于数据库,主要是LocalDb。
二、连接数据库
当使用NuGet安装完Entity Framework后,在配置文件中会自动加入entityFramework节,里面有defaultConnectionFactory元素,如下:
1: <?xml version="1.0" encoding="utf-8"?> 2: <configuration> 3: <configSections> 4: <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> 5: <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 6: </configSections> 7: <entityFramework> 8: <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"> 9: <parameters> 10: <parameter value="Data Source=(localdb)\\v11.0; Integrated Security=True; MultipleActiveResultSets=True" /> 11: </parameters> 12: </defaultConnectionFactory> 13: </entityFramework> 14: </configuration>
在没有提供具体数据库连接的情况下,EF默认使用这一配置。如上面代码中,默认会连接到LocalDb,数据库的名称为上下文完全限定名(命名空间+类名)。以前经常提到默认连接到.\\SQLEXPRESS,因为安装的版本不同。
EF中提供了两个连接工厂:SqlConnectionFactory和SqlCeConnectionFactory。使用方式分别如下:
1: Database.DefaultConnectionFactory = new SqlConnectionFactory("Data Source=.;Database=Test;UId=sa;Pwd=sasa;MultipleActiveResultSets=True");
或
1: Database.DefaultConnectionFactory = new SqlConnectionFactory("Data Source=.;Database=Test;User=sa;Password=sasa;MultipleActiveResultSets=True");
和
1: Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");
在配置文件和代码中同时有DefaultConnectionFactory的情况下,代码中的优先。
下面,写一个简单的控制台程序。代码如下:
1: namespace ConnectDatabase 2: { 3: class Program 4: { 5: static void Main(string[] args) 6: { 7: using (TestContext ctx = new TestContext()) 8: { 9: var blog = new Blog() 10: { 11: Name = "EF" 12: }; 13: blog.Posts.Add(new Post() 14: { 15: Title = "连接数据库", 16: Content = "这是连接数据库的测试", 17: Creationdate = DateTime.Now, 18: Blog = blog 19: }); 20: ctx.Blogs.Add(blog); 21: ctx.SaveChanges(); 22: 23: foreach (var item in ctx.Blogs) 24: { 25: Console.WriteLine(item.Name); 26: } 27: } 28: } 29: } 30: 31: public class TestContext : DbContext 32: { 33: protected override void OnModelCreating(DbModelBuilder modelBuilder) 34: { 35: base.OnModelCreating(modelBuilder); 36: } 37: 38: public DbSet<Blog> Blogs { get; set; } 39: public DbSet<Post> Posts { get; set; } 40: } 41: 42: public class Blog 43: { 44: public Blog() 45: { 46: Posts = new List<Post>(); 47: } 48: 49: public int Id { get; set; } 50: public string Name { get; set; } 51: public virtual List<Post> Posts { get; set; } 52: } 53: 54: public class Post 55: { 56: public int Id { get; set; } 57: public string Title { get; set; } 58: public string Content { get; set; } 59: public DateTime Creationdate { get; set; } 60: public virtual Blog Blog { get; set; } 61: } 62: }
使用默认连接配置,生成的数据库名称为:ConnectDatabase.TestContext,如下图所示:
重写上面配置有以下方法:
1.在配置文件中添加connectionStrings,name和上下文类名一致。
1: <connectionStrings> 2: <add name="TestContext1" connectionString="Data Source=(localdb)\\v11.0;Database=Test;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/> 3: </connectionStrings>
2.同1,但是name和上下文类名不一致。这就需要修改TextContext代码,如下:
1: public TestContext() : this("TestContext1") { } 2: 3: public TestContext(string nameOrConnectionString) 4: : base(nameOrConnectionString) 5: { 6: 7: }
或
1: public TestContext() 2: : base("name=TestContext1") 3: { 4: 5: }
或
1: public TestContext():base("TestContext1"){}
下面给出连接具体数据库的配置:
1.连接Sql Server数据库
1: <connectionStrings> 2: <add name="TestContext" connectionString="Data Source=.;Database=Test;User=sa;Password=sasa;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/> 3: </connectionStrings>
2.连接Sql Server Compact 4.0
1: <connectionStrings> 2: <add name="TestContext" connectionString="Data Source=|DataDirectory|\\Test.sdf" providerName="System.Data.SqlServerCe.4.0"/> 3: </connectionStrings>
3.连接mysql 5.5
连接MySql数据库需要安装mysql提供程序mysql-connector-net-6.6.4,本文最后提供这些工具的下载地址。
1: <connectionStrings> 2: <add name="TestContext" 3: connectionString="User Id=root;server=localhost;password=sasa;database=test1" 4: providerName="MySql.Data.MySqlClient" /> 5: </connectionStrings>
三、数据库初始化
1.关闭初始化
1: Database.SetInitializer<TestContext>(null);
2.CreateDatabaseIfNotExists
这是Entity Framework的默认初始化策略,没有必要设置它,如果真的需要设置,如下:
1: Database.SetInitializer(new CreateDatabaseIfNotExists<TestContext>());
3.DropCreateDatabaseWhenModelChanges
如果模型发生了改变,则删除并重建数据库。
1: Database.SetInitializer(new DropCreateDatabaseWhenModelChanges<TestContext>());
4.DropCreateDatabaseAlways
无论模型和数据库匹配与否,都删除并重建数据库。
1: Database.SetInitializer(new DropCreateDatabaseAlways<TestContext>());
5.Database.Initialize可以强制初始化,即使在当前AppDomain中已经发生了。下面我写个单元测试程序,来演示这一点:
1: [TestClass] 2: public class UnitTest1 3: { 4: [TestMethod] 5: public void TestForceInitialize() 6: { 7: //说明一点:我Demo中的TestContext和Microsoft.VisualStudio.TestTools.UnitTesting.TestContext冲突了,所以写成了ConnectDatabase.TestContext 8: //Arrage 9: Database.SetInitializer(new DropCreateDatabaseAlways<ConnectDatabase.TestContext>()); 10: //Act 11: using (ConnectDatabase.TestContext ctx = new ConnectDatabase.TestContext()) 12: { 13: ctx.Database.Initialize(force: true); 14: ctx.Blogs.Add(new ConnectDatabase.Blog() 15: { 16: Name = "强制初始化1" 17: }); 18: ctx.SaveChanges(); 19: } 20: using (ConnectDatabase.TestContext ctx = new ConnectDatabase.TestContext()) 21: { 22: ctx.Database.Initialize(force: true); 23: ctx.Blogs.Add(new ConnectDatabase.Blog() 24: { 25: Name = "强制初始化2" 26: }); 27: ctx.SaveChanges(); 28: } 29: ConnectDatabase.Blog blog = null; 30: using (ConnectDatabase.TestContext ctx = new ConnectDatabase.TestContext()) 31: { 32: blog = ctx.Blogs.FirstOrDefault(); 33: } 34: 35: //Assert 36: Assert.IsNotNull(blog); 37: Assert.AreEqual("强制初始化2", blog.Name); 38: 39: } 40: }
测试结果:
因为设置的初始化策略为DropCreateDatabaseAlways,每一次调用Database.Initialize,参数为true,都会重新删除并创建数据库。
四、Seed数据
创建数据库时初始化一些数据,首先自定义初始化策略,重写Seed方法,代码如下:
1: public class DropCreateDatabaseWithSeedData : DropCreateDatabaseAlways<TestContext> 2: { 3: protected override void Seed(TestContext context) 4: { 5: context.Blogs.Add(new Blog() 6: { 7: Name = "种子数据1" 8: }); 9: context.Blogs.Add(new Blog() 10: { 11: Name = "种子数据2" 12: }); 13: //注意没有调用context.SaveChanges(),base.Seed(context)会调用 14: base.Seed(context); 15: } 16: }
下面是测试程序:
1: [TestMethod] 2: public void SeedData() 3: { 4: Database.SetInitializer(new DropCreateDatabaseWithSeedData()); 5: List<ConnectDatabase.Blog> blogList = null; 6: using (ConnectDatabase.TestContext ctx = new ConnectDatabase.TestContext()) 7: { 8: blogList = ctx.Blogs.OrderBy(t => t.Id).ToList(); 9: } 10: Assert.AreEqual(2, blogList.Count); 11: Assert.AreEqual("种子数据1", blogList[0].Name); 12: Assert.AreEqual("种子数据2", blogList[1].Name); 13: }
测试结果:
五、创建索引
在Seed方法中,使用ExecuteSqlCommand创建索引,代码如下:
1: protected override void Seed(TestContext context) 2: { 3: context.Database.ExecuteSqlCommand("CREATE INDEX IX_Test_Name ON Blogs (Name)"); 4: context.Blogs.Add(new Blog() 5: { 6: Name = "种子数据1" 7: }); 8: context.Blogs.Add(new Blog() 9: { 10: Name = "种子数据2" 11: }); 12: //注意没有调用context.SaveChanges(),base.Seed(context)会调用 13: base.Seed(context); 14: }
六、结束语
mysql相关工具下载地址:
2.mysql-connector-net-6.6.4.msi
3.mysql-workbench-gpl-5.2.44-win32.msi
本篇中主要讲了Entity Framework连接数据库、初始化的一些知识,跟题目”工欲善其事必先利其器“有点不符,但仔细想想也相差不了多远,解决了最基本的,后面的才能更顺利。
点击查看《Entity Framework实例详解》系列的其他文章。
如果遇到问题,可以访问Entity Framework社区,网址是www.ef-community.com
转:http://www.cnblogs.com/nianming/archive/2012/11/04/2753183.html
以上是关于转:工欲善其事必先利其器—Entity Framework实例详解的主要内容,如果未能解决你的问题,请参考以下文章