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. 安装包

package.PNG

3. 添加实体

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

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


table.PNG

现在可以开始编写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. 添加迁移文件,执行迁移

add-migration.PNG

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


product.PNG

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;
            }
        }
    }

操作成功:


insert.PNG
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 内存管理模块 看目录 1. 为何有堆栈,说说堆栈的区别,分别存放什么,为什么要有堆和栈,对象为何放到堆上,有没有栈...
    剁椒鸡蛋zy阅读 337评论 0 0
  • 1 字符串和二进制之间的相互转换 字符串转化为二进制:encode() 默认为utf8,若为gbk需要注明 ...
    嘻嘻吖_94e2阅读 201评论 0 0
  • 今天,让我们聊一聊mongodb: Mongodb,分布式文档存储数据库,由C++语言编写,旨在为WEB应用提供可...
    霹雳火_4617阅读 186评论 0 1
  • MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方...
    善_46f5阅读 131评论 0 1
  • Ajax与JSON学习 一、Ajax学习 1.什么是ajax? Ajax是使用客户端脚本与Web服务器交换数据的W...
    袁小胜阅读 231评论 0 0