EF6和EF core大同小异,区别在于:
SqlServer:EntityFramework(没有core)
mysql:MySql.Data.EntityFramework.dll:
不能override/没有OnConfiguring()方法,需要通过构造函数来指定数据库。最常用的方式是:
首先在配置文件(App.config/Web.config)中添加连接字符串(复习:获取connection字符串)
<connectionStrings> <add name="bang" providerName="System.Data.SqlClient" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=17bang;Integrated Security=True;"/> </connectionStrings>
注意:
public SqlDbContext() : base("name=bang")其中name=也可以省略:
public SqlDbContext() : base("bang")
如果配置文件中没有连接字符串的配置,且VS中已配置了LocalDB,就会以该字符串为数据库名自动新建数据库。
此外,也可以直接传入连接字符串:
public SqlDbContext() : base(@"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=18bang;Integrated Security=True;")
mysql需要在DbContext类上加特性:
[DbConfigurationType(typeof(MySqlEFConfiguration))] public class MysqlDbContext : DbContext
因为在演示EFcore的时候已经安装了Migration Tool,所以可以直接检查EF6的migration能否使用:
GET-HELP about_EntityFramework6
返回以上图形,表示一切OK。
EF6上需要首先执行Enable-Migrations。
Enable-Migrations会生成Migrations\Configuration.cs文件。
PS:EF6也为我们提供了自动Migration的选项。
public Configuration() { AutomaticMigrationsEnabled = false; }但一般不建议使用,因为无法追踪版本(参考:https://stackoverflow.com/questions/11806570/automaticmigrationsenabled-false-or-true)
运行时会出现如下高亮提示:
Both Entity Framework 6 and Entity Framework Core are installed. The Entity Framework 6 tools are running. Use 'EntityFrameworkCore\Update-Database' for Entity Framework Core.
这告诉我们:
然后其他命令和EF core一样,
但如果要Update-Database到某个特定版本的话,需要加
只是方法名/类名的区别:
SqlDbContext context = new SqlDbContext(); Database database = context.Database; database.Delete(); database.Create();
public SqlContext() : base("17bang") { //从控制台输出 Database.Log = Console.WriteLine; //从VS的out window输出 Database.Log = s => Debug.Write(s); //写入磁盘文件:c:\\ef.log Database.Log = s => File.AppendAllText("c:\\ef.log", s); }
@想一想@:为什么不能直接
Database.Log = Debug.Write;因为特性:
[Conditional("DEBUG")] public static void Write(string message)
EF6的继承和EF core大致相同,略
对应Owned Entity,添加该特性的类不会独立映射成一张表,而是若干列。
[ComplexType] public class Bed /*: BaseEntity 不需要Id */
然后注意引用它是不能让它为NULL值,否则会报错:
public Bed SleepIn { get; set; } = new Bed();
其他可参考这里……
普通/默认的1:n和n:n和EF core没有区别。
但是1:1需要显式的指定主外键关系。
EF6中没有HasOne()和WithOne(),而是配合使用:
细分1:1和1:0/1,并指定主外键关系。比如,Student之前Bed在后
modelBuilder.Entity<Student>() .HasRequired(s => s.SleepIn) //Student需要SleepIn才能持久化 //.WithRequiredDependent() //Bed做为Dependent(依赖,主键值由Student赋予) .WithRequiredPrincipal() //Bed做为Principal(PK,Identity)
modelBuilder.Entity<Student>() .HasRequired(s => s.SleepIn) .WithOptional(b => b.Student) //参数不能省略
但注意:这时候不能显式声明影子属性,比如SleepInId,StudentId……否则会将他们视为普通属性映射
没有ThenInclude(),只有Select()
context.Teachers.Where(t => t.Id > 5) .Include(t => t.Students .Select(ts => ts.SleepIn).Select(b=>b.Room)) .Include(t => t.Students .Select(ts => ts.StudyIn)) .FirstOrDefault();
默认开启,只要关联属性上标记了virtual关键字
当项目变得复杂时,因为各种各样的原因,可能出现把一个DbContext中取出来的entity,放入另外一个DbContext中处理。比如:
private static Teacher getTeacher(int id) { using (SqlDbContext context = new SqlDbContext()) { context.Teachers.Find(id);
SqlDbContext context = new SqlDbContext(); context.Find<Major>(4).Teacher = getTeacher(1);
我们是想将已有的Teacher赋值给Major,但EF6却是新建了一个Teacher。@想一想@:为什么?因为对于major所在的DbContex而言,另一个DbContext生成的teacher是“全新”的(即使有Id)
在SaveChanges()的时候,EF6和EF core使用了不同的机制来确定一个entity的状态:
C#中的DateTime如果没有赋值的话,就是0000年1月1日 0时0分;
在EF6中DateTime自动被映射成datetime类型,最小值1900-01-01 00:00:00,无法存放上述日期值。
所以要么指定映射类型:
modelBuilder.Entity<Student>() .Property(s => s.Enroll).HasColumnType("datetime2");要么设置为可空类型(推荐):
public DateTime? Enroll { get; set; }
比EF core少一些方法:
(对应FromRawSql()等)只有名为SqlQuery()的方法,可以传入自定义的sql语句和参数:
context.Students.SqlQuery("sql语句", new SqlParameter( context.Database.SqlQuery<Student>("sql语句", new SqlParameter(
在EF的Linq语句后调用ToString()方法,可以查看其SQL语句:
string sql = context.Students.Where(s=>s.Age > 18).ToString();
基于EF6上完成之前作业
多快好省!前端后端,线上线下,名师精讲
更多了解 加: