【EF框架】DbContext的使用: https://blog.csdn.net/zmh458/article/details/78935172
DBComtext使用
DbContext
类是EntityFramework
(简称 EF
)中的一个类,可以理解为一个数据库对象的实例。在EF
中,无需手动的拼接SQL
语句对数据库进行增删改查,而是通过DbContext
来进行相应操作。
DbContext类
DbContext是负责与数据交互作为对象的主要类。DbContext负责以下活动:
(1)EntitySet: DbContext包含映射到数据库表的所有实体的实体集(DbSet )。
(2)查询(Querying): DbContext将LINQ-to-Entities查询转换为SQL查询并将其发送到数据库。
(3)更改跟踪(Change Tracking):跟踪实体在从数据库查询后发生的更改。
(4)持久数据(Persisting Data):它还根据实体的状态对数据库执行插入,更新和删除操作。
(5)缓存(Caching): DbContext默认进行一级缓存。它存储在上下文类生命周期中已经被检索的实体。
(6)管理关系(Manage Relationship): DbContext还使用DB-First或Model-First方法使用CSDL,MSL和SSDL或者使用Code-First方法使用流利的API来管理关系。
(7)对象实现(Object Materialization): DbContext将原始表数据转换为实体对象。
EF core跟以前的EF差距非常大,view(视图)无法通过dbfirst生成了,存储过程也一样(虽然我现在开始转codEFirst了)。 然而,如果真的想直接执行sql语句怎么办? 我们发现context下的Database属性跟以前也不一样了,只能做些事务操作,没有执行sql了。可以执行sql的变成了每张具体的表(DbSet)下面的FromSql方法了(需要显式引用Microsoft.EntityFrameworkCore命名空间)。 但是这个方法存在问题,只能返回该表类型的结果,无法返回任意类型。
可以使用linq查询多张表的数据
public List QueryAUser()
{
//定义了上下文实体
excellentmcoinEntities dbcontext = new excellentmcoinEntities();
var allUser = (from u in dbcontext.t_user
join g in dbcontext.t_grade on u.gradeID equals g.gradeID
orderby u.totalMcoin descending
select new userModel()
{
userID = u.userID,
userName = u.userName,
userGrade = g.userGrade,
totalMcoin = u.totalMcoin,
gradeID = g.gradeID,
}).ToList();
return allUser;
}
EFCore的级联删除(可优化)减少查询
public override async Task> DeleteAsync(Guid Id)
{
var data = await DbSet.Include(x => x.UserAuthApplyOfDriver)
.Include(x => x.UserAuthApplyOfVehicle)
.Include(x => x.UserAuthApplyOfEnterprise)
.Include(x => x.UserAuthApplyOfLinePrice)
.Include(x => x.User)
.FirstOrDEFaultAsync(x => x.Id ==Id);
if (data.UserAuthApplyOfVehicle != null)
{
var vehicles = Context.Set().Where(x => x.UserAuthApplyId == Id);
Context.Set().RemoveRange(vehicles);
}
if (data.UserAuthApplyOfDriver != null)
{
var drivers = Context.Set().Where(x => x.UserAuthApplyId == Id);
Context.Set().RemoveRange(drivers);
}
if (data.UserAuthApplyOfEnterprise != null)
{
var enterprises = Context.Set().Where(x => x.UserAuthApplyId == Id);
Context.Set().RemoveRange(enterprises);
}
if (data.UserAuthApplyOfLinePrice != null)
{
var linePrices = Context.Set().Where(x => x.UserAuthApplyId == Id);
Context.Set().RemoveRange(linePrices);
}
return await base.DeleteAsync(Id);
}
使用FluentAPI
流畅接口是由Martin Fowler和Eric Evans创造的,流畅API意味着你构建一个API需要遵循以下要点:
1.API用户能够容易理解API
2.API为完成一个任务能够执行一系列动作,比如Java中可以看成是一系列方法调用,方法链。
3.每个方法名称应该是与业务领域相关的专门术语
4.API应该能提示指导API用户下一步用什么,以及某个时刻用户可能采取的操作。
参考:https://www.jdon.com/48272
为了更改约定和映射,可以使用 DbContext 类中的 OnModelCreating 方法。
注意 : 数据库将某个字段从不能为空改为可以非空,需要在数据库中去除约束,还得在OnModelCreating
中去除必填代码约束。因为 OnModelCreating
执行的优先级也高
在OnModelCreating方法下使用
public class FluentApiDb:DbContext
{
public DbSet Courses { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity().Property(o => o.Title).HasMaxLength(20);
}
}
新增一个类,在OnModelCreating中引用
public class FluentApiDb:DbContext
{
public DbSet Teacher { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new TeacherMap());
modelBuilder.Configurations.Add(new StudentMap());
base.OnModelCreating(modelBuilder);
}
}
通过反射动态加入。利:自动加入,无需人工反复加;弊:影响性能
public class FluentApiDb:DbContext
{
public DbSet Teacher { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => !String.IsNullOrEmpty(type.Namespace))
.Where(type => type.BaseType != null && type.BaseType.IsGenericType
&& type.BaseType.GetGenericTypeDEFinition() == typeof(EntityTypeConfiguration<>));
foreach (var type in typesToRegister)
{
dynamic configurationInstance = Activator.CreateInstance(type);
modelBuilder.Configurations.Add(configurationInstance);
}
base.OnModelCreating(modelBuilder);
}
}
FluentAPI详细用法
- 设置主键
cs modelBuilder.Entity
().HasKey(t => t.Name); - 设置联合主键
cs modelBuilder.Entity
().HasKey(t =>new{t.Name,t.ID} ); - 取消数据库字段标识(取消自动增长)
cs modelBuilder.Entity
().Property(t=>t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); - 设置数据库字段标识(自动增长)
cs modelBuilder.Entity
().Property(t =>t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 设置字段最大长度
modelBuilder.Entity
().Property(t => t.Name).HasMaxLength(100); - 设置字段为必需
cs modelBuilder.Entity
().Property(t =>t.Id).IsRequired(); 属性不映射到数据库
modelBuilder.Entity
().Ignore(t => t.A); - 将属性指定数据库列名:
cs modelBuilder.Entity
() .Property(t => t.A) .HasColumnName("A_a"); - 级联删除(数据库默认是不级联删除的)
cs modelBuilder.Entity
().HasRequired(t => t.Department).WithMany(t => t.Courses).HasForeignKey(d => d.DepartmentID).WillCascadeOnDelete(); - 设置为Timestamp
cs modelBuilder.Entity
() .Property(t => t.Timestamp) .IsRowVersion(); 表1对0..1(Instructor实体可以包含零个或一个OfficeAssignment)
modelBuilder.Entity
().HasRequired(t => t.Instructor).WithOptional(t => t.OfficeAssignment); - 表1对1
cs modelBuilder.Entity
().HasRequired(t => t.OfficeAssignment).WithRequiredPrincipal(t => t.Instructor); - 表1对n(Department为主表)
cs modelBuilder.Entity
() .HasRequired(c => c.Department) .WithMany(t => t.Staffs) - 指定外键名(指定表Staff中的字段DepartmentID为外键)
cs modelBuilder.Entity
() .HasRequired(c => c.Department) .WithMany(t => t.Staffs) .Map(m => m.MapKey("DepartmentID")); - 表n对n
cs modelBuilder.Entity
() .HasMany(t => t.Instructors) .WithMany(t => t.Courses) 表n对n指定连接表名及列名
cs modelBuilder.Entity
() .HasMany(t => t.Instructors) .WithMany(t => t.Courses) .Map(m => { m.ToTable("CourseInstructor"); m.MapLEFtKey("CourseID"); m.MapRightKey("InstructorID"); });
参考:
EF Core中如何正确地设置两张表之间的关联关系:https://www.cnblogs.com/OpenCoder/p/9820064.html
官方文档:https://docs.microsoft.com/zh-cn/EF/EF6/modeling/code-first/fluent/relationships
翻译官方文档:http://www.aizhengli.com//entity-framework-5-code-first/104/entity-framework-code-first-fluent-api-hasmany-withrequired.html