1、MySql环境准备
(1)ADO.NET driver
安装ADO.NET操作MySql的驱动“Connector/NET”,下载地址如下:
(2)VS访问MySql对象的支持(包括Entity Framework)
A、通过安装“MySQL for Visual Studio”以支持访问MySql对象及VS的设计器
B、通过NuGet安装“MySql.Data.Entity.EF6”以支持访问MySql对象
2、配置
(1)EntityFramework
通过NuGet安装EntityFramework,安装完后会自动在config里添加如下的section
驱动(默认为MSSql驱动,及指向的本地DB的实例MSSQLLocalDB-VS自带的简单的DB):
(2)MySql.Data.MySqlClient驱动
通过“1.2”的方式安装后,需确保项目引用到了如下两个组件
否则在程序集里添加
在config里会自动添加或需手动指定EF的适配器
(3)connectionString
通过connectionString配置的连接串的优先级大于defaultConnectionFactory
(4)注意
A、无法为具有固定名称“MySql.Data.MySqlClient”的 ADO.NET 提供程序加载在应用程序配置文件中注册的实体框架提供程序类。
需要确保对DLL以应用,及版本后的正确。
B、利用VS自带的命令行工具查看PublicKeyToken
SN –T “XXXXXXXXXXXXXX.dll”
3、实现
(1)DB上下文类
通过添加空的Code First模型或者手工添加类继承DbContext
配置好对应的connectionString后即可通过EF访问DB
using (ModelCaiji context=new ModelCaiji())
{
var query= context.Database.SqlQuery("select Name from filminfo;");
return query.ToList();
}
(2)实体及与table的映射
添加实体及与table的映射以便支持相应实体的操作及生成DB
///
/// 实体
///
public class FilminfoEntity
{
public int Id { get; set; }
public string Name { get; set; }
}
///
/// 实体与数据表的映射(Fluent API)
///
public class FilminfoEntityMap : EntityTypeConfiguration
{
public FilminfoEntityMap()
{
#region Generated
//ToTable("filminfo");
HasKey(table => table.Id);
Property(table => table.Id)
.HasColumnName("Id")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
.IsRequired();
Property(table => table.Name)
.HasColumnName("Name");
#endregion Generated
}
}
(3)DB初始化策略
EF上下文支持如下初始化DB的策略
public ModelCaiji()
: base("name=ModelCaiji")
{
//数据库初始化策略
//Database.SetInitializer(new CreateDatabaseIfNotExists());//(默认策略)如果数据库不存在,那么就创建数据库。
//Database.SetInitializer(new DropCreateDatabaseIfModelChanges());//如果模型变化了,数据库就会被重新创建,原来的数据库被删除掉了。
//Database.SetInitializer(new DropCreateDatabaseAlways());//每次运行程序都会重新创建数据库,这在开发和调试的时候非常有用。
Database.SetInitializer(null);//关闭策略,不自动创建DB
//Database.SetInitializer(new CustomDatabaseInitializer());//自定义策略
}
自定义策略:
///
/// 自定义数据库初始化策略
///
public class CustomDatabaseInitializer : DropCreateDatabaseAlways where TModelCaiji : ModelCaiji
{
protected override void Seed(TModelCaiji context)
{
//添加电影数据
FilminfoEntity filminfoEntity = new FilminfoEntity()
{
Name = "斗破苍穹"
};
context.FilminfoEntity.Add(filminfoEntity);
base.Seed(context);
}
}
(4)约定
可移除EF自带的约定
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
//添加实体与数据表的映射
modelBuilder.Configurations.Add(new FilminfoEntityMap());
//移除约定
modelBuilder.Conventions.Remove();//(移除此约定将不会改变DbSet对应的表名)如果在Map里没有明确指定表名,将使用DbSet实体集的名称当作表名并且会强制转会为复数格式
modelBuilder.Conventions.Remove();//移除级联删除
modelBuilder.Conventions.Remove();
}
4、其它
(1)DbContext实例初始化问题
A、对于一般的BS系统为了提高与DB交互的性能需确保数据库上下文DbContext对象在同一操作线程内唯一
//CallContext:是线程内部唯一的独用的数据槽(一块内存空间)
//传递DbContext进去获取实例的信息,在这里进行强制转换。
AppDbContext dbContext = CallContext.GetData("DbContext") as AppDbContext;
if (dbContext == null) //线程在数据槽里面没有此上下文
{
lock (_lockObj)
{
if (dbContext == null)
{
dbContext = new AppDbContext(); //如果不存在上下文的话,创建一个EF上下文
//我们在创建一个,放到数据槽中去
CallContext.SetData("DbContext", dbContext);
}
}
}
return dbContext;
B、对于类似多线程的环境需避免数据库上下文DbContext对象重复使用
5、参考
Entity Framework 6官方文档
Entity Framework 5.0 Code First全面学习
EF三种编程方式的区别Database first ,Model first ,code first
EF 配置(SqlServer,Mysql)
EF Code First:实体映射,数据迁移,重构