Skip to content
FreeSql 官方文档FreeSql 官方文档
指南
扩展
服务支持
github icon
  • 指南

      • DbContext
        • 特性
          • 安装
            • 如何使用
              • 优先级
                • 说明
                  • 合并机制
                    • 联级保存
                      • 实体变化事件
                      • IFreesql 和 Context
                      • DB First
                        • 表达式函数
                          • 事务
                            • 过滤器
                              • ADO
                                • AOP✨
                                  • 读写分离
                                    • 分表分库
                                      • 多租户
                                        • 性能
                                          • 你不知道的功能 ✨

                                          DbContext

                                          author iconnicyecalendar icon2021年2月5日timer icon大约 3 分钟word icon约 1028 字

                                          此页内容
                                          • 特性
                                          • 安装
                                          • 如何使用
                                          • 优先级
                                          • 说明
                                          • 合并机制
                                          • 联级保存
                                          • 实体变化事件

                                          # DbContext

                                          FreeSql.DbContext 实现类似 EFCore 使用习惯,跟踪对象状态,最终通过 SaveChanges 方法提交事务。

                                          # 特性

                                          • Select/Attach 快照对象,Update 只更新变化的字段;
                                          • Add/AddRange 插入数据,适配各数据库优化执行 ExecuteAffrows/ExecuteIdentity/ExecuteInserted;
                                          • AddOrUpdate 插入或更新;
                                          • SaveMany 方法快速保存导航对象(一对多、多对多);

                                          # 安装

                                          dotnet add package FreeSql.DbContext

                                          # 如何使用

                                          0、通用方法,为啥是 0???

                                          using (var ctx = fsql.CreateDbContext()) {
                                            //var db1 = ctx.Set<Song>();
                                            //var db2 = ctx.Set<Tag>();
                                          
                                            var item = new Song { };
                                            ctx.Add(item);
                                            ctx.SaveChanges();
                                          }
                                          
                                          1
                                          2
                                          3
                                          4
                                          5
                                          6
                                          7
                                          8

                                          注意:DbContext 对象多线程不安全

                                          1、在 OnConfiguring 方法上配置与 IFreeSql 关联

                                          public class SongContext : DbContext {
                                          
                                            public DbSet<Song> Songs { get; set; }
                                            public DbSet<Tag> Tags { get; set; }
                                          
                                            protected override void OnConfiguring(DbContextOptionsBuilder builder) {
                                              builder.UseFreeSql(GlobalVar.fsql);
                                              //这里直接指定一个静态的 IFreeSql 对象即可,切勿重新 Build()
                                            }
                                          
                                            //每个 DbContext 只触发一次
                                            protected override void OnModelCreating(ICodeFirst codefirst)
                                            {
                                              codefirst.Entity<Song>(eb =>
                                              {
                                                eb.ToTable("tb_song");
                                                eb.Ignore(a => a.Field1);
                                                eb.Property(a => a.Title).HasColumnType("varchar(50)").IsRequired();
                                                eb.Property(a => a.Url).HasMaxLength(100);
                                          
                                                eb.Property(a => a.RowVersion).IsRowVersion();
                                                eb.Property(a => a.CreateTime).HasDefaultValueSql("current_timestamp");
                                          
                                                eb.HasKey(a => a.Id);
                                                eb.HasIndex(a => new { a.Id, a.Title }).IsUnique().HasName("idx_xxx11");
                                          
                                                //一对多、多对一
                                                eb.HasOne(a => a.Type).HasForeignKey(a => a.TypeId).WithMany(a => a.Songs);
                                          
                                                //多对多
                                                eb.HasMany(a => a.Tags).WithMany(a => a.Songs, typeof(Song_tag));
                                              });
                                          
                                              codefirst.Entity<SongType>(eb =>
                                              {
                                                eb.HasMany(a => a.Songs).WithOne(a => a.Type).HasForeignKey(a => a.TypeId);
                                          
                                                eb.HasData(new[]
                                                {
                                                  new SongType
                                                  {
                                                    Id = 1,
                                                    Name = "流行",
                                                    Songs = new List<Song>(new[]
                                                    {
                                                      new Song{ Title = "真的爱你" },
                                                      new Song{ Title = "爱你一万年" },
                                                    })
                                                  },
                                                  new SongType
                                                  {
                                                    Id = 2,
                                                    Name = "乡村",
                                                    Songs = new List<Song>(new[]
                                                    {
                                                      new Song{ Title = "乡里乡亲" },
                                                    })
                                                  },
                                                });
                                              });
                                          
                                              codefirst.SyncStructure<SongType>();
                                              codefirst.SyncStructure<Song>();
                                            }
                                          }
                                          
                                          public class SongType {
                                            public int Id { get; set; }
                                            public string Name { get; set; }
                                          
                                            public List<Song> Songs { get; set; }
                                          }
                                          public class Song {
                                            [Column(IsIdentity = true)]
                                            public int Id { get; set; }
                                            public string Title { get; set; }
                                            public string Url { get; set; }
                                            public DateTime CreateTime { get; set; }
                                          
                                            public int TypeId { get; set; }
                                            public SongType Type { get; set; }
                                            public List<Tag> Tags { get; set; }
                                          
                                            public int Field1 { get; set; }
                                            public long RowVersion { get; set; }
                                          }
                                          public class Song_tag {
                                            public int Song_id { get; set; }
                                            public Song Song { get; set; }
                                          
                                            public int Tag_id { get; set; }
                                            public Tag Tag { get; set; }
                                          }
                                          public class Tag {
                                            [Column(IsIdentity = true)]
                                            public int Id { get; set; }
                                          
                                            public string Name { get; set; }
                                          
                                            public List<Song> Songs { get; set; }
                                          }
                                          
                                          1
                                          2
                                          3
                                          4
                                          5
                                          6
                                          7
                                          8
                                          9
                                          10
                                          11
                                          12
                                          13
                                          14
                                          15
                                          16
                                          17
                                          18
                                          19
                                          20
                                          21
                                          22
                                          23
                                          24
                                          25
                                          26
                                          27
                                          28
                                          29
                                          30
                                          31
                                          32
                                          33
                                          34
                                          35
                                          36
                                          37
                                          38
                                          39
                                          40
                                          41
                                          42
                                          43
                                          44
                                          45
                                          46
                                          47
                                          48
                                          49
                                          50
                                          51
                                          52
                                          53
                                          54
                                          55
                                          56
                                          57
                                          58
                                          59
                                          60
                                          61
                                          62
                                          63
                                          64
                                          65
                                          66
                                          67
                                          68
                                          69
                                          70
                                          71
                                          72
                                          73
                                          74
                                          75
                                          76
                                          77
                                          78
                                          79
                                          80
                                          81
                                          82
                                          83
                                          84
                                          85
                                          86
                                          87
                                          88
                                          89
                                          90
                                          91
                                          92
                                          93
                                          94
                                          95
                                          96
                                          97
                                          98
                                          99
                                          100
                                          101

                                          使用的时候与 EFCore 类似:

                                          long id = 0;
                                          
                                          using (var ctx = new SongContext()) {
                                          
                                            var song = new Song { };
                                            await ctx.Songs.AddAsync(song);
                                            id = song.Id;
                                          
                                            var adds = Enumerable.Range(0, 100)
                                              .Select(a => new Song { Create_time = DateTime.Now, Is_deleted = false, Title = "xxxx" + a, Url = "url222" })
                                              .ToList();
                                            await ctx.Songs.AddRangeAsync(adds);
                                          
                                            for (var a = 0; a < adds.Count; a++)
                                              adds[a].Title = "dkdkdkdk" + a;
                                          
                                            ctx.Songs.UpdateRange(adds);
                                          
                                            ctx.Songs.RemoveRange(adds.Skip(10).Take(20).ToList());
                                          
                                            //ctx.Songs.Update(adds.First());
                                          
                                            adds.Last().Url = "skldfjlksdjglkjjcccc";
                                            ctx.Songs.Update(adds.Last());
                                          
                                            //throw new Exception("回滚");
                                          
                                            await ctx.SaveChangesAsync();
                                          }
                                          
                                          1
                                          2
                                          3
                                          4
                                          5
                                          6
                                          7
                                          8
                                          9
                                          10
                                          11
                                          12
                                          13
                                          14
                                          15
                                          16
                                          17
                                          18
                                          19
                                          20
                                          21
                                          22
                                          23
                                          24
                                          25
                                          26
                                          27
                                          28
                                          29

                                          2、注入方式使用

                                          public void ConfigureServices(IServiceCollection services) {
                                            services.AddSingleton<IFreeSql>(Fsql);
                                            services.AddFreeDbContext<SongContext>(options => options.UseFreeSql(Fsql));
                                          }
                                          
                                          1
                                          2
                                          3
                                          4

                                          在 mvc 中获取:

                                          IFreeSql _orm;
                                          public ValuesController(SongContext songContext) {
                                          }
                                          
                                          1
                                          2
                                          3

                                          # 优先级

                                          OnConfiguring > AddFreeDbContext

                                          # 说明

                                          • DbContext 操作的数据在最后 SaveChanges 时才批量保存;
                                          • DbContext 内所有操作,使用同一个事务;
                                          • 当实体存在自增时,或者 Add/AddRange 的时候主键值为空,会提前开启事务;
                                          • 支持同步/异步方法;

                                          # 合并机制

                                          db.Add(new Xxx()); db.Add(new Xxx()); db.Add(new Xxx());

                                          这三步,会合并成一个批量插入的语句执行,前提是它们没有自增属性。

                                          适用 Guid 主键,Guid 主键的值不用设置,交给 FreeSql 处理即可,空着的 Guid 主键会在插入时获取有序不重值的 Guid 值。

                                          又比如:

                                          db.Add(new Xxx()); db.Add(new Xxx()); db.Update(xxx); db.Add(new Xxx());

                                          Guid Id 的情况下,执行三次命令:前两次插入合并执行,update 为一次,后面的 add 为一次。

                                          # 联级保存

                                          请移步文档 【联级保存】

                                          # 实体变化事件

                                          全局设置:

                                          fsql.SetDbContextOptions(opt => {
                                            opt.OnEntityChange = report => {
                                              Console.WriteLine(report);
                                            };
                                          });
                                          
                                          1
                                          2
                                          3
                                          4
                                          5

                                          单独设置 DbContext 或者 UnitOfWork:

                                          var ctx = fsql.CreateDbContext();
                                          ctx.Options.OnEntityChange = report => {
                                            Console.WriteLine(report);
                                          };
                                          
                                          var uow = fsql.CreateUnitOfWork();
                                          uow.OnEntityChange = report => {
                                            Console.WriteLine(report);
                                          };
                                          
                                          1
                                          2
                                          3
                                          4
                                          5
                                          6
                                          7
                                          8
                                          9

                                          参数 report 是一个 List 集合,集合元素的类型定义如下:

                                          public class ChangeInfo {
                                            public object Object { get; set; }
                                            public EntityChangeType Type { get; set; }
                                            /// <summary>
                                            /// Type = Update 的时候,获取更新之前的对象
                                            /// </summary>
                                            public object BeforeObject { get; set; }
                                          }
                                          public enum EntityChangeType { Insert, Update, Delete, SqlRaw }
                                          
                                          1
                                          2
                                          3
                                          4
                                          5
                                          6
                                          7
                                          8
                                          9
                                          变化类型说明
                                          Insert实体对象被插入
                                          Update实体对象被更新
                                          Delete实体对象被删除
                                          SqlRaw执行了 SQL 语句

                                          SqlRaw 目前有两处地方比较特殊:

                                          • 多对多联级更新导航属性的时候,对中间表的全部删除操作;
                                          • 通用仓储类 BaseRepository 有一个 Delete 方法,参数为表达式,而并非实体;
                                          int Delete(Expression<Func<TEntity, bool>> predicate);
                                          
                                          1

                                          DbContext.SaveChanges,或者 Repository 对实体的 Insert/Update/Delete,或者 UnitOfWork.Commit 操作都会最多触发一次该事件。

                                          edit icon在 GitHub 上编辑此页open in new window
                                          上次编辑于: 2022/5/16 下午8:50:28
                                          贡献者: luoyunchong,igeekfan
                                          下一页
                                          IFreesql 和 Context
                                          Copyright © 2018-present nicye
                                          Copyright © 2022 nicye

                                          该应用可以安装在你的 PC 或移动设备上。这将使该 Web 应用程序外观和行为与其他应用程序相同。它将在出现在应用程序列表中,并可以固定到主屏幕,开始菜单或任务栏。此 Web 应用程序还将能够与其他应用程序和你的操作系统安全地进行交互。

                                          详情