Entity Framework Core - CURD

【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<userModel> 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<MangeResult<UserAuthApplyOfBase>> 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<UserAuthApplyOfVehicle>().Where(x => x.UserAuthApplyId == Id);
                Context.Set<UserAuthApplyOfVehicle>().RemoveRange(vehicles);
        }
        if (data.UserAuthApplyOfDriver != null)
        {
                var drivers = Context.Set<UserAuthApplyOfDriver>().Where(x => x.UserAuthApplyId == Id);
                Context.Set<UserAuthApplyOfDriver>().RemoveRange(drivers);
        }

        if (data.UserAuthApplyOfEnterprise != null)
        {
                var enterprises = Context.Set<UserAuthApplyOfEnterprise>().Where(x => x.UserAuthApplyId == Id);
                Context.Set<UserAuthApplyOfEnterprise>().RemoveRange(enterprises);
        }

        if (data.UserAuthApplyOfLinePrice != null)
        {
                var linePrices = Context.Set<UserAuthApplyOfLinePrice>().Where(x => x.UserAuthApplyId == Id);
                Context.Set<UserAuthApplyOfLinePrice>().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<Course> Courses { get; set; }
     protected override void OnModelCreating(ModelBuilder modelBuilder)
     {
         modelBuilder.Entity<Course>().Property(o => o.Title).HasMaxLength(20);
     }
 }

新增一个类,在OnModelCreating中引用

 public class FluentApiDb:DbContext
 {
     public DbSet<Teacher> 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> 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<x>().HasKey(t => t.Name);
  • 设置联合主键
    cs modelBuilder.Entity<x>().HasKey(t =>new{t.Name,t.ID} );
  • 取消数据库字段标识(取消自动增长)
    cs modelBuilder.Entity<x>().Property(t=>t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
  • 设置数据库字段标识(自动增长)
    cs modelBuilder.Entity<Teacher>().Property(t =>t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
  • 设置字段最大长度

     modelBuilder.Entity<ClassA>().Property(t => t.Name).HasMaxLength(100);
  • 设置字段为必需
    cs modelBuilder.Entity<ClassA>().Property(t =>t.Id).IsRequired();
  • 属性不映射到数据库

     modelBuilder.Entity<ClassA>().Ignore(t => t.A);
  • 将属性指定数据库列名:
    cs modelBuilder.Entity<ClassA>() .Property(t => t.A) .HasColumnName("A_a");
  • 级联删除(数据库默认是不级联删除的)
    cs modelBuilder.Entity<Course>().HasRequired(t => t.Department).WithMany(t => t.Courses).HasForeignKey(d => d.DepartmentID).WillCascadeOnDelete();
  • 设置为Timestamp
    cs modelBuilder.Entity<OfficeAssignment>() .Property(t => t.Timestamp) .IsRowVersion();
  • 表1对0..1(Instructor实体可以包含零个或一个OfficeAssignment)

      modelBuilder.Entity<OfficeAssignment>().HasRequired(t => t.Instructor).WithOptional(t => t.OfficeAssignment);
  • 表1对1
    cs modelBuilder.Entity<Instructor>().HasRequired(t => t.OfficeAssignment).WithRequiredPrincipal(t => t.Instructor);
  • 表1对n(Department为主表)
    cs modelBuilder.Entity<Staff>() .HasRequired(c => c.Department) .WithMany(t => t.Staffs)
  • 指定外键名(指定表Staff中的字段DepartmentID为外键)
    cs modelBuilder.Entity<Staff>() .HasRequired(c => c.Department) .WithMany(t => t.Staffs) .Map(m => m.MapKey("DepartmentID"));
  • 表n对n
    cs modelBuilder.Entity<Course>() .HasMany(t => t.Instructors) .WithMany(t => t.Courses)
  • 表n对n指定连接表名及列名
    cs modelBuilder.Entity<Course>() .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

上一篇:MySql CURD操作(数据的增删改查)


下一篇:终极CURD-4-java8新特性