EF CodeFirst-----简单demo示例
关于EF CodeFirst的文章院子里有很多的学习资料,但大多数都是一些讲Model通过特性或是Fluent API与数据库之间形成映射的关系,看了相关的文章之后,Model如何映射到数据还是有些迷糊,最近看了qouoww的这个系列文章http://www.cnblogs.com/qouoww/archive/2011/12/31/2309066.html,感觉不错,写下一个简单的demo作为总结,一起学习共勉。
既然是采用CodeFirst的方式来编程的话,那么首先很明显一点我们得自己定义一个数据库上下文对象,如下所示:
public class BaseDbContext<TContext> : DbContext
where TContext : BaseDbContext<TContext>, new()
{
public BaseDbContext()
: base("DefaultConnection")
{ }
}
构造函数中引用的基类构造函数,如下所示:
// Constructs a new context instance using the given string as the name or connection
// string for the database to which a connection will be made. See the class
// remarks for how this is used to create a connection.
//
// 参数:
// nameOrConnectionString:
// Either the database name or a connection string.
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
public DbContext(string nameOrConnectionString);
因此EF中默认的数据库连接字符串就是配置文件中默认的连接字符串:
接下来我们我们创建一个数据库迁移配置类,这个类主要是用来封装由Model变化而引起的数据库结构的变化。如下所示:
public sealed class TestConfiguration : DbMigrationsConfiguration<TestDbContext>
{
public TestConfiguration()
{
this.AutomaticMigrationsEnabled = true;
this.AutomaticMigrationDataLossAllowed = true;
}
}
这样我们就启动了迁移功能。紧接着我么来创建数据库迁移类来封装数据库迁移的相关方法,如下所示:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(TestDatabaseMigrator), "MigrateDatabase")]
namespace CodeFirst.Context
{
public class TestDatabaseMigrator
{
public static void MigrateDatabase()
{
DbMigrator dbMigrator = new DbMigrator(new TestConfiguration());
dbMigrator.Update();
using (TestDbContext dbContext = new TestDbContext())
{
dbContext.Database.Initialize(true);
}
}
}
}
我们可以看到DbMigrator类是以数据库迁移类作为参数实例化的, dbMigrator.Update()这句代码可以保证我们的目标数据库都是与Model映射成的最新的数据库结构。注意这一句话:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(TestDatabaseMigrator), "MigrateDatabase")]
WebActivator 允许您定义一个 PreApplicationStartMethod 属性,用于标记作为东西您获取 Web 应用程序启动时调用的方法,这样就可以保证先初始化我们的数据库。WebActivatorEx还有一个PostApplicationStartMethod方法,改方法是在全局的asax Application_Start 后调用的方法。
TestDbContext的定义如下:
public class TestDbContext : BaseDbContext<TestDbContext>
{
public DbSet<Test> MyTest { get; set; }
}
TestModel定义如下,用于与数据库映射成对应的表,请记住Model必须要有主键,否则会报错!
public class Test
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
我们启动web应用程序后,在vs中附带的数据库中可以看到EF创建的数据库:数据库名是与配置文件中的数据库名一致,而表名则是根据默认的约定生成的,即Model+s就是默认生成的表名。
但是上面看起来很别扭,首先,数据库要生成到SqlServer中,那么我们修改下配置文件:
<add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog= EF.CodeFirst;Integrated Security=True" providerName="System.Data.SqlClient" />
然后我们想自己定义它生成的表名及相关的索引,注释之类的,那么我们首先要创建一个数据库初始化器:
/// <summary>
/// 数据库初始化器
/// </summary>
/// <typeparam name="T"></typeparam>
public class InitializerComposite<T>: IDatabaseInitializer<T>
where T : DbContext
{
private readonly List<IDatabaseInitializer<T>> initializers; public InitializerComposite(params IDatabaseInitializer<T>[] databaseInitializers)
{
this.initializers = new List<IDatabaseInitializer<T>>();
this.initializers.AddRange(databaseInitializers);
} /// <summary>
/// 执行数据库初始化器
/// </summary>
/// <param name="context"></param>
public void InitializeDatabase(T context)
{
foreach (var initializer in this.initializers)
{
initializer.InitializeDatabase(context);
}
}
}
同时我们需要修改下数据库上下文对象的基类,加入如下代码:
/// <summary>
/// 获取表的名字
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public virtual string GetTableName(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
} string modelName = type.Name;
return modelName;
} /// <summary>
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (modelBuilder == null)
{
throw new ArgumentNullException("modelBuilder");
}
// 定义表名规则
modelBuilder.Entities().Configure(entity => entity.ToTable(this.GetTableName(entity.ClrType)));
Database.SetInitializer(new InitializerComposite<TContext>());
}
表名直接就是利用Model的类名来生成,启动web程序,我们打开SqlServer,我们可以看到:数据库名在配置文件中指定,表名就是Model的类名Test,而不是默认的Tests。我们看下生成的表的结构:
当然生成的字段的数据长度都是系统默认生成的长度,这个我们也可以修改,将在后面的文章中进行说明。
但是有时候我们想在生成数据库的时候,同时有一些初始化的数据呢?这个时候我们就要在数据库迁移配置类中的Seed中加入一些初始数据:
/// <summary>
/// 对数据库中的进行相关的初始化操作
/// </summary>
/// <param name="context"></param>
protected override void Seed(TestDbContext context)
{
var test1 = new Test() { Name="aa", Age=12 };
var test2= new Test() { Name = "bb", Age = 12 };
var test3 = new Test() { Name = "cc", Age = 12 };
var tests = new List<Test> { test1, test2, test3};
tests.ForEach(c => context.MyTest.AddOrUpdate(x => x.Name, c));
context.SaveChanges();
base.Seed(context);
}
我们再次打开数据库,可以发现,生成的表里面已经有了我们初始化的数据了:
好了,EF CodeFirst的一些简单运用写到这里,日后将陆续更新。
EF CodeFirst-----简单demo示例的更多相关文章
- Ext简单demo示例
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- EF CodeFirst 实例Demo
一直想搞一个EFCodeFirst的Demo,让自己通过实例真正了解CodeFirst,方便以后有需求的时候可以有思路.网上查了很多资料,发现很多博主的文章大量重复,根据推荐步骤走并不一定能够成功,而 ...
- EF CodeFirst简单实例
运行环境:VS2012,添加的EntityFramework为6.0.2 版本不用太关心,只要知道原理就行了: 基本代码就这几行: namespace ConsoleApplication1 { ...
- EF CodeFirst生成数据库到Sqlserver中
EF CodeFirst简单实例这篇文章介绍了如何用EF去快速生成数据库.但是这个并没有生成到sqlserver中,总觉得不爽.下面就来讲一下,如何将数据库生成到sqlserver中. 按照EF Co ...
- Django实战(一)之简单Demo
菜鸟教程上Django安装可供参考: 参考链接: http://www.runoob.com/django/django-install.html 菜鸟教程上如果不行的话,下面博客网址可以供参考 Li ...
- 写一个EF的CodeFirst的Demo
写一个EF的CodeFirst的Demo 今天打算写一个关于EF的CodeFirs的一个小Demo.先略说一个EF的三种与数据库,怎么说,叫映射么,好吧,那就这么叫吧,就是一个是ModelFirst就 ...
- 3.翻译系列:EF Code-First 示例(EF 6 Code-First系列)
原文链接:http://www.entityframeworktutorial.net/code-first/simple-code-first-example.aspx EF 6 Code-Firs ...
- EF CodeFirst系列(1)---CodeFirst简单入门
1.什么是CodeFirst 从EF4.1开始,EF可以支持CodeFirst开发模式,这种开发模式特别适用于领域驱动设计(Domain Driven Design,大名鼎鼎的DDD).在CodeFi ...
- 1.【使用EF Code-First方式和Fluent API来探讨EF中的关系】
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/relationship-in-entity-framework-using-code-firs ...
随机推荐
- mysql存储过程和函数使用实例
1.需求:根据输入的年份,月份,和当前系统的年份比较,不满1年按1年计算,多出1年11个月也按1年计算. 2.计算得出来的使用年份,计算车辆残值. 3.存储过程 DELIMITER $$ USE `d ...
- JobClient学习------作业提交与初始化
public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); ...
- ASP.NET 处理get/post数据方式
1.GET方式 NameValueCollection coding; coding = HttpUtility.ParseQueryString(Request.Url.Query, Encodin ...
- Javascript实现 图片的无缝滚动
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- java 驼峰命名
jstl中前台jsp页面调用对象中的属性时, 用的是小驼峰命名法. 例如:${item.createTime} 1.小驼峰式命名法(lower camel case): 第一个单字以小写字母开始,第二 ...
- Learn CSS
韩顺平老师的CSS讲的还是很简单的,仅作入门. div+css的介绍 div+css是什么. div元素是用来为HTML文档内大块(block-level)的内容提供结构和背景的元素. css是 ...
- hdu2025查找最大元素
#include<iostream> #include<stdio.h> #include<math.h> #include<stdlib.h> #in ...
- lintcode:打劫房屋 III
题目 打劫房屋 III 在上次打劫完一条街道之后和一圈房屋之后,窃贼又发现了一个新的可以打劫的地方,但这次所有的房子组成的区域比较奇怪,聪明的窃贼考察地形之后,发现这次的地形是一颗二叉树.与前两次偷窃 ...
- 如何成为高级java程序员
或许您已经读过我的那篇小文<如何成为java初级程序员>,那里面只介绍了成为一个JAVA程序员应该具备的一些知识.我相信您绝不会只想着做一个初级的程序员,上了软件开发的小船,您肯定有着远大 ...
- C++名字空间/C++命名空间
0.序言 名字空间是C++提供的一种解决符号名字冲突的方法. 一个命令空间是一个作用域,在不同名字空间中命名相同的符号代表不同的实体. 通常,利用定义名字空间的办法,可以使模块划分更加方便,减少模块间 ...