1. Dotnet9首页
  2. .NET
  3. .NET相关

efcore系列一 efcore执行的基本流程

最近终于闲下来了,有点时间来写一下使用efcore过程中遇到的的一些细节问题。这个系列会从基础开始,可能会比较啰嗦(~ ̄▽ ̄)~。

开发环境 VS2019 .NET Core2.2 mysql8.0

会用到的包,列一下:

Microsoft.EntityFrameworkCore
Microsoft.EntityFrameworkCore.Tools
Pomelo.EntityFrameworkCore.MySql
Microsoft.Extensions.Configuration
Microsoft.Extensions.Configuration.Json

为什么不用官方的包MySql.Data.EntityFrameworkCore,我只能说,从2018年4月份开始使用corefirst的体验来看,官方的驱动做的实在是烂,对数据迁移不够友好,至2019年群里的小伙伴还在吐槽不支持GUID(未核实)。

接下来是正文:

1. 新建一个控制台项目EFCoreFirst,做一下简单的演示就不用web项目了。

添加一个appsetting.json配置文件,属性设置始终复制

{
  "ConnectionString": "server=127.0.0.1;port=3306;database=efcore_demo;uid=sa;pwd=123456;"
}

2. 安装包

efcore系列一 efcore执行的基本流程

3. 添加实体

ef core是关于访问数据库的,但是这个数据库是从哪里来的呢?ef core提供了两个选项:通过ef core创建它,称为code first,或者手动创建数据库,称为database first。

这个例子中会使用codefirst创建一个简单的数据库,包含两张表:Products 包含产品信息,Order 包含订单信息

efcore系列一 efcore执行的基本流程

现在可以开始编写efcore相关的代码了,在创建任何数据库访问代码之前,需要编写两个基本部分:
3.1 由ef core映射到数据库中表的类
3.2 应用程序的DbContext,用于配置和访问数据库的类

products类:

[Table("product")]
    public class Products
    {
        /// <summary>
        /// key显示将ProductId设为主键,但是我们已经使用了efcore命名约定,它告诉efcore属性ProductId是主键,所以可以省略
        /// </summary>
        [Key]
        public virtual int ProductId { get; set; }

        /// <summary>
        /// 产品名称
        /// </summary>
        [StringLength(50)]
        public virtual string Name { get; set; }

        /// <summary>
        /// 产品数量
        /// </summary>
        public virtual int Count { get; set; }

        /// <summary>
        /// 价格
        /// </summary>
        public virtual Decimal Price { get; set; }

        /// <summary>
        /// 外键
        /// </summary>
        public virtual int OrderId { get; set; }

        /// <summary>
        /// Order属性是efcore导航属性。efcore在save中使用这个来查看products否附加了order类,如果附加了order类,它将设置外键orderId
        /// 这里有一个新的命名约定 efcore知道OrderId是一个外键,当它与Order类的主键名称一致
        /// </summary>
        public virtual Order Order { get; set; }
    }

Order类:

[Table("order")]
    public class Order
    {
        [Key]
        public virtual int OrderId { get; set; }
        
        /// <summary>
        /// 订单编号
        /// </summary>
        [StringLength(25)]
        public virtual string OrderCode { get; set; }

        /// <summary>
        /// 买家名称
        /// </summary>
        [StringLength(25)]
        public virtual string Buyer { get; set; }
    }

4. 添加数据库上下文

public class AppDbContext:DbContext
    {
        private static string ConnStr;

        static AppDbContext()
        {
            var builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsetting.json");
            var config = builder.Build();
            ConnStr = config["ConnectionString"];
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseMySql(ConnStr);
        }

        
        public DbSet<Products> Products { get; set; }
    }

5. 添加迁移文件,执行迁移

efcore系列一 efcore执行的基本流程

查看生成的数据库表,可以看到表product表按预期生成

efcore系列一 efcore执行的基本流程

efcore生成迁移文件的过程,以products为例子:
5.1 在AppDbContext中查找所有DbSet<T> 属性,这里找到了Products类,获取到了表名称(从Table特性中,未设置则默认为类名)
5.2 查看DbSet<T>中所有类T(这里是Products类),并查看其属性以计算列名、类型等。它还查找类和或属性上提供额外建模信息的特殊属性如StringLength特性
5.3 查找DbSet<T>类所引用的任何类(Products类中的Order)。在这个例子中,Products类引用了Order类,所以efcore也会扫描它。它对Order类的属性执行与步骤2中对Products相同的操作。
5.4 efcore在应用程序的DbContext中运行OnModelCreating方法,这里我们未重写这个方法,该方法可以添加一些配置。
5.5 efcore根据以上步骤收集的所有信息创建数据库的内部模型,生成迁移文件。

6. 尝试操作数据

public class Program
    {
        static void Main(string[] args)
        {
            AddProduct();
            var product = GetSingleProduct();
            Console.WriteLine($"{product?.ProductId}--{product?.Name}");

            Console.ReadLine();

        }

        public static void AddProduct()
        {
            using (var dbContext=new AppDbContext())
            {
                var product = new Products()
                {
                    Name = "apple",
                    Price = 3.0M,
                    Count = 10,
                    Order = new Order {
                        OrderCode = "0001",
                        Buyer="xiaoming"
                    }
                };

                dbContext.Add<Products>(product);
                dbContext.SaveChanges();
            }
        }

        public static Products GetSingleProduct()
        {
            using (var dbContext = new AppDbContext())
            {
                var product = dbContext.Products.FirstOrDefault();
                return product;
            }
        }
    }

操作成功:

efcore系列一 efcore执行的基本流程

原文出处:简书【smilekop】

原文链接:https://www.jianshu.com/p/b99aa2e3d95d

本文观点不代表Dotnet9立场,转载请联系原作者。

发表评论

登录后才能评论