序:这里我以netcore3.1来做基本底层,net5或者net6或者更高,我觉得举一反三即可!

1.首先第一步:创建项目:

   我创建了一个关于数据处理的类库,一个模型类库,一个控制台;

 2.引用 相关 包

   在数据层 引用 Microsoft.EntityFrameworkCore.SqlServer;  Microsoft.EntityFrameworkCore.Tools2个包

   在控制台(一般来说是ui层)引用Microsoft.EntityFrameworkCore.Design  包,这样基本就可以了.我是用SQL server数据库做的demo

3.在模型层进行 类的创建,举个例子:

    如下:联赛和俱乐部是1对多关系,  俱乐部和球员是1对多关系;   每个字段对应数据库中相应属性,我们在代码里可以 用 相关特性 对 字段进行 设置(如:最大字符数,是否必填,属性类型等等)

/// <summary>
    /// 联赛
    /// </summary>
    public class League
    {
        public int Id { get; set; }        [Required]
        [MaxLength(100)]
        public string Name { get; set; }        [Required,MaxLength(50)]
        public string Country { get; set; }
    } 
/// <summary>
    /// 俱乐部
    /// </summary>
    public class Club
    {
        //public Club() 
        //{
        //    Players = new List<Player>();
        //}
        public int Id { get; set; }
        public string Name { get; set; }
        public string City { get; set; }
        [Column(TypeName ="date")]
        public DateTime DateOfEstablishment { get; set; }//成立的日期
        public string History { get; set; }
        public League League { get; set; }
        public List<Player> Players { get; set; } = new List<Player>();
    } 
/// <summary>
    /// 球员
    /// </summary>
    public class Player
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public DateTime DateOfBirth { get; set; }        public List<GamePlayer> GamePlayers { get; set; } = new List<GamePlayer>();
        public int ResumeId { get; set; }
        public Resume Resume { get; set; }
    }

这里没有举例多对多的关系,如果是多对多的关系,那么肯定是有一个中间类作为连接形成 n:1;n:1 ,然后成为n:n

4.在数据层创建 Democontext  类.继承一下DbContext 类;  如下:(我们用DBFirst的方法进行研究)

   在这个类中,第一步要写DBSet<上诉类> xxxx {get;set;}

                      写完关联类后,就该连接数据库了.

      连接数据库要重写 OnConfiguring  类,然后optionsBuilder.UseSqlServer("这里是你的SQL server数据库的相关连接")

      完了就基础框架就出来了,下边是我自己加的一些东西,如需要可参考

public class DemoContext:DbContext
    {
        /// <summary>
        /// 全局设置  数据变化不被追踪
        /// </summary>
        //public DemoContext() 
        //{
        //    ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        //}        #region  第二步:     创建连接字符串
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseLoggerFactory(ConsoleLoggerFactory)//打印日志在控制台上
                .UseSqlServer("Server=127.0.0.1;Database=EFDemoDB;uid=sa;pwd=123456");
        }
        #endregion        #region  定义联合主键
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<GamePlayer>().HasKey(x=>new { x.GameId,x.PlayerId});            //建立 一对一  关系(fluent api)
            modelBuilder.Entity<Resume>().HasOne(x => x.Player)
                .WithOne(x => x.Resume)
                .HasForeignKey<Resume>(x=>x.PlayerId);
        }
        #endregion        #region  第一步:   将类写为DbSet格式的属性  
        public DbSet<League> Leagues { get; set; }
        public DbSet<Club> Clubs { get; set; }
        public DbSet<Player> Players { get; set; }
        public DbSet<Game> Games { get; set; }
        public DbSet<Resume> Resumes { get; set; }
        #endregion        public static readonly ILoggerFactory ConsoleLoggerFactory =
            LoggerFactory.Create(builder=> 
            {
                builder.AddFilter((category,level)=>
                category==DbLoggerCategory.Database.Command.Name 
                && level ==LogLevel.Information
                ).AddConsole();//category:种类
            });
    }

   5.数据迁移

  打开工具中的  程序包管理控制台,下拉框选中 关于数据的类库

   

Add-Migration Init  //这样就会在数据层生成一个相关文件夹
       update-database   //这样数据库就可以看到刚才写的类了

   6.增,删,查,改

using var context = new DemoContext();//全局都要用到的上下文对象

     6.1  增加:

context.Leagues.Add(le1);//增加一条数据
  context.Leagues.AddRange(le2,le3);//增加同类型多条数据
  context.AddRange(le4,club1);//增加不同类型的多条数据 ;这里会自动识别 属于哪个类别

  当然不要忘记 :context.SaveChanges();  要不然数据库不会执行

     6.2 删除:   只能删除被追踪的数据

  要做删除,首先要找到要删除哪条数据,然后才能删除

 

var led1 = context.Leagues.Where(x=>x.Name.Contains("r")).ToList();
  context.Leagues.RemoveRange(led1);
  context.SaveChanges();

  6.3 查询:  查询会涉及到  模糊查询,精确查询,分页查询 ,排序(正序/倒叙)等查询  

var lens = context.Leagues.OrderBy(x=>x.Id).Last(x => x.Country == "意大利" || x.Country.Contains("西"));
            //var lens = context.Leagues.Where(x=>x.Country=="意大利"||x.Country.Contains("西")).ToList();

这里注意:只有ToList之后,数据库才是真正的执行了.  那么还有哪些方法是调用完才会执行数据库呢?下边我总结了一些,不够请补充

//ToList() First() FirstOrDefault() Single()
            //SingleOrDefault()   Last()    LastOrDefault()
            //Count(),LongCount(),Min(),Max(),Average(),  Sum()   Find():这个方法只能传  [主键Id]

 6.4修改: 修改的话一般会遇到  追踪和非追踪的问题

//传统修改:先找出要修改的数据,然后对要修改的进行重新赋值 修改的时候也是只能修改被追踪的数据
            //var le5 = context.Leagues.FirstOrDefault();

            //le5.Name = "意甲";

            //int k = context.SaveChanges(); //一般项目 都是前后端分离的, 前端传递过来的 基本都是json字符串什么的,这时候就不能用追踪了
            var le6 = context.Leagues.AsNoTracking().First();//这个AsNoTracking 可以对全局设置:在context类中进行设置            le6.Name = "意大利甲级联赛";
             context.Leagues.Update(le6);
            var w = context.SaveChanges();

 

至此,一套基本的efcore的增删查改就完成了,更复杂的需要小伙伴们根据实际情况考虑