EF Core

一、简介

EF Core Official Documentation: https://docs.microsoft.com/ef/core。EF Core可以访问很多不同的数据库。EFCore提供了两种开发方式:

  • Code-First
  • Database-First
DatabaseNuGet Package
SQL ServerMicrosoft.EntityFrameworkCore.SqlServer
MySQLMySql.Data.EntityFrameworkCore
PostgreSQLNpgsql.EntityFrameworkCore.PostgreSQL
SQLiteMicrosoft.EntityFrameworkCore.SQLite
SQL CompactEntityFrameworkCore.SqlServerCompact40
In-memoryMicrosoft.EntityFrameworkCore.InMemory

二、安装

如果我们项目中使用的是SQLServer数据库,那么我们需要安装两个包:

在这里插入图片描述

它提供了我们访问SQL Server数据库的功能。然后还需要安装:
在这里插入图片描述

它可以在项目设计阶段提供迁移(migration)、搭建(scaffolding)等功能。

三、Database-First

这种开放模式意味着已经有数据库了,然后我们需要做的就是根据已有的数据库创建我们自己的实体对象,当然这一过程不需要我们手动进行了,因为EFCore可以帮我们快速完成这一操作。

本地已有数据库,连接字符串如下:

Data Source=DESKTOP-P7UORUH\SQLEXPRESS;Initial Catalog=TestDB;User ID=heater;Password=123456;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False

TestDB数据库中有三张表:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在程序包管理器控制台(PMC)中执行如下命令:

OK
PM> Scaffold-DbContext "Data Source=DESKTOP-P7UORUH\SQLEXPRESS;Initial Catalog=TestDB;User ID=heater;Password=123456;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

然后输出如下:

Build started...
Build succeeded.
To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.

最后我们可以在项目文件中看到新增的文件:

在这里插入图片描述

有三个表对应的三个entity class,这三个类应该很好理解;还有一个context class,那么这个是干嘛的呢?

    public partial class TestDBContext : DbContext
    {
        public TestDBContext()
        {
        }

        public TestDBContext(DbContextOptions<TestDBContext> options)
            : base(options)
        {
        }

        public virtual DbSet<Class> Classes { get; set; }
        public virtual DbSet<Student> Students { get; set; }
        public virtual DbSet<Teacher> Teachers { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {

        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
        
        }
    }

TestDBContext继承自DbContext,它有两个构造函数,在子类中我们重写了两个方法。

  • OnConfiguring:用于配置此context对象使用的数据库,这个方法在上下文实例化的时候会被调用,为了防止被重复配置,一般会使用IsConfigured属性进行判断。
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer("Data Source=DESKTOP-P7UORUH\\SQLEXPRESS;Initial Catalog=TestDB;User ID=heater;Password=123456;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
            }
        }

值得一提的是,连接字符串一般不会直接写在源码中,而是写在配置文件中。但是实际在ASP.NET Core项目中,我们一般不在这个重写方法中进行数据库的配置,而是在IOC中注册,然后从appSetting.json中获取连接字符串。

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TestDBContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("TestDBContext")));
        }
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",

  "ConnectionStrings": {
    "TestDBContext": "Data Source=DESKTOP-P7UORUH\\SQLEXPRESS;Initial Catalog=TestDB;User ID=heater;Password=123456;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
  }
}
  • OnModelCreating:配置entity class,具体怎么配我也不知道。。。

DbSet映射对应的表:

        public virtual DbSet<Class> Classes { get; set; }
        public virtual DbSet<Student> Students { get; set; }
        public virtual DbSet<Teacher> Teachers { get; set; }

四、Code-First

故名思意就是我们在源码中已经有数据模型了,现在需要创建对应的数据库。

4.1 安装包

PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer
PM> Install-Package Microsoft.EntityFrameworkCore.Tools

4.2 创建模型和上下文

    [Table("StudentMaster")]
    public class Student
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Required]
        [Column("StudentName",TypeName ="nvarchar(20)")]
        public string Name { get; set; }

        [Column(TypeName ="nvarchar(10)")]
        public GenderType Gender { get; set; }

        [Column(TypeName ="decimal(5,2)")]
        public float AvgScore { get; set; }

        [Column(TypeName ="binary(3)")]
        public byte[] Scores { get; set; }

        [StringLength(50)]
        public string Address { get; set; }

        [Column(TypeName = "DateTime2")]
        public DateTime Birthday { get;set; }

        public int ClassId { get; set; }

        public DateTime CreateDate { get; set; }
    }


    public enum GenderType
    {
        Male,
        Female
    }

    public class Class
    {
        public int Id { get; set; }
        public string ClassName { get; set; }
        public string TeacherName { get; set; }
    }
    public class SchoolDbContext : DbContext
    {
        public DbSet<Class> Classes { get; set; }
        public DbSet<Student> Students { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source = vm1.si-in.com; Initial Catalog = SchoolDb; User ID = sa; Password = Silicon@123");
        }
    }

4.3 Data Annotations Attributes

4.4.1 Table

通常情况下,数据库表的名称会与类名称一致,除非显示指定表名称。[Table(“Name”)]使用在类上。

4.4.2 Column

通常情况下,数据库列名会与属性名称一致,除非显示指定另外一个。

Column Attribute: [Column (string name, Properties:[Order = int],[TypeName = string])

  • name: Name of a column in a db table.
  • Order: Order of a column, starting with zero index. (Optional)
  • TypeName: Data type of a column. (Optional)

4.4.3 Primary key

通常情况下,属性名称中带id(无论大小写)映射到数据库中的时候都会被设置为主键。[Key]使用在主键上。

4.4.4 Generated Values

可以使用[DatabaseGenerated(DatabaseGeneratedOption.Identity)]特性来标注自增的值。

4.4.5 NotMapped

通常情况下,带有getter和setter的公开属性,都会被映射到数据库中,除非使用NotMapped 。

4.4.6 Required

被标注为[Required]的属性将是一个NOT NULL列。

4.4.7 ForeignKey

暂时不解释

4.4 Add a Migration

PM>  add-migration CreateSchoolDB
Build started...
Build succeeded.
To undo this action, use Remove-Migration.

执行上述命令后会在本地项目文件中创建如下文件:

在这里插入图片描述

但是此时数据库还未创建。然后需要执行如下指令:

PM> update-database –verbose

这样我们就可以在数据库中看到我们想要创建的。

在这里插入图片描述

如果后续发现业务有变化,model中需要添加新的字段,那么我们在model中添加字段后只需要重新执行命令行即可,但是记得add-migration后面需要新名称,然后再更新数据库。例如:

PM> Add-Migration CreateSchoolDbNew
PM> update-Database

4.5 Querying

需要使用Linq辅助。

4.6 Saving Data

4.6.1 连接场景

using SchoolDbContext context = new SchoolDbContext();

            Student student = new Student
            {
                Name = "张娟",
                Gender = GenderType.Female,
                AvgScore = 99.9f,
                Scores = new byte[] { 100, 100, 50 },
                Address = "武汉市白沙洲",
                Birthday = new DateTime(1998, 8, 7),
                ClassId = 11,
                CreateDate =DateTime.Now,
            };

            context.Students.Add(student);//只是保存在了上下文中
            context.SaveChanges();//真正保存到数据库中
            using SchoolDbContext context = new SchoolDbContext();

            Student student = context.Students.First();
            student.Name = "朱道宽";
            context.SaveChanges();
            using SchoolDbContext context = new SchoolDbContext();

            Student student = context.Students.First();
            context.Students.Remove(student);
            context.SaveChanges();

4.7 ChangeTracker

指的上下文中的实体与数据库中实体之间的差异。

            Student student = new Student
            {
                Name = "朱道宽",
                Gender = GenderType.Female,
                AvgScore = 99.9f,
                Scores = new byte[] { 100, 100, 50 },
                Address = "武汉市白沙洲",
                Birthday = new DateTime(1998, 8, 7),
                ClassId = 11,
                CreateDate = DateTime.Now,
            };

            using (SchoolDbContext context = new SchoolDbContext())
            {
                context.Students.Add(student);//只是保存在了上下文中

                var entries = context.ChangeTracker.Entries();
                foreach (var entry in entries)
                {
                    Console.WriteLine(entry.Entity.GetType() + "=>" + entry.State.ToString());
                }
            };
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值