iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 > .Net 常用ORM框架对比:EF Core、FreeSql、SqlSuger
  • 790
分享到

.Net 常用ORM框架对比:EF Core、FreeSql、SqlSuger

摘要

  前言:   最近由于工作需要,需要选用一种ORM框架,也因此对EF Core、Freesql、SqlSuger作简单对比。个人认为各有有优势,存在即合理,不然早就被淘汰了是吧,所以如何选择因人而议、因项目而议,下面开始正题。   本篇


	.Net 常用ORM框架对比:EF Core、FreeSql、SqlSuger
[数据库教程]

  前言:   最近由于工作需要,需要选用一种ORM框架,也因此对EF Core、Freesql、SqlSuger作简单对比。个人认为各有有优势,存在即合理,不然早就被淘汰了是吧,所以如何选择因人而议、因项目而议,下面开始正题。   本篇文章不讲解基础知识,如有需要可移步到相应官网:EF Core官方文档:https://docs.microsoft.com/zh-cn/ef/,FreeSql官方文档:Http://freesql.net/guide.html,SqlSuger官方文档:http://www.codeisbug.com/Home/Doc   环境说明:项目环境ASP .net core WEB api,目标框架:.Net 5,依赖包: 技术图片   技术图片 一:准备数据实体类
 1     /// 
 2     /// 班级
 3     /// 
 4     public class ClassGrade
 5     {
 6         [FreeSql.DataAnnotations.Column(IsIdentity = true, IsPrimary = true)]//FreeSql
 7         [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]//Sugar
 8         [Key,DatabaseGenerated(DatabaseGeneratedOption.Identity)]  //Ef设置自增(int类型默认自增)
 9         public int Id { get; set; }
10         public string Name { get; set; }
11         [SugarColumn(IsIgnore = true)]
12         public virtual ICollection Students { get; set; }
13         [SugarColumn(IsIgnore = true)]
14         public virtual ICollection Classs { get; set; }//
15     }
16     /// 
17     /// 课程
18     /// 
19     public class Course
20     {
21         [FreeSql.DataAnnotations.Column(IsIdentity = true, IsPrimary = true)]//FreeSql
22         [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]//Sugar
23         [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]  //Ef设置自增(int类型默认自增)
24         public int Id { get; set; }
25         public string Name { get; set; }
26         public virtual string Teacher { get; set; }
27         [SugarColumn(IsIgnore = true)]
28         public virtual ICollection ClassStudents { get; set; }//班级学生
29         [SugarColumn(IsIgnore = true)]
30         public virtual ICollection Students { get; set; }//选修学生
31     }
32     /// 
33     /// 学生
34     /// 
35     public class Student
36     {
37         [FreeSql.DataAnnotations.Column(IsIdentity = true, IsPrimary = true)]//FreeSql
38         [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]//Sugar
39         [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]  //Ef设置自增(int类型默认自增)
40         public int Id { get; set; }
41         public string Name { get; set; }
42         public int Age { get; set; }
43         public int Sex { get; set; }
44         public int ClassId { get; set; }
45         [SugarColumn(IsIgnore = true)]
46         public virtual ClassGrade Class { get; set; }
47         [SugarColumn(IsIgnore = true)]
48         public virtual ICollection Courses { get; set; }//辅修课、自选课
49     }
50 {
51     /// 
52     /// 中间表(班级-课程)
53     /// 
54     public class MiddleClassCourse
55     {
56         [FreeSql.DataAnnotations.Column(IsIdentity = true, IsPrimary = true)]//FreeSql
57         [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]//Sugar
58         [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]  //Ef设置自增(int类型默认自增)
59         public int Id { get; set; }
60         public int ClassId { get; set; }
61         [SugarColumn(IsIgnore = true)]
62         public virtual ClassGrade Class { get; set; }
63         public int CourseId { get; set; }
64         [SugarColumn(IsIgnore = true)]
65         public virtual Course Course { get; set; }
66     }
67     /// 
68     /// 中间表(学生-课程)
69     /// 
70     public class MiddleStudentCourse
71     {
72         [FreeSql.DataAnnotations.Column(IsIdentity = true, IsPrimary = true)]//FreeSql
73         [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]//Sugar
74         [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]  //Ef设置自增(int类型默认自增)
75         public int Id { get; set; }
76         public int CourseId { get; set; }
77         [SugarColumn(IsIgnore = true)]
78         public virtual Course Course { get; set; }
79         public int StudentId { get; set; }
80         [SugarColumn(IsIgnore = true)]
81         public virtual Student Student { get; set; }
82     }
二:Code First 1. EF的流程相对比较复杂,但是功能也更强大,具体流程我在这里就不仔细叙述了,下面是EF的DbContext类
    public class EfDbContext : DbContext
    {
        /// 
        /// 指定静态ILoggerFactory
        /// 
        public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); });

        public EfDbContext() { }

        public EfDbContext(DbContextOptions options)
            : base(options)
        {
        }

        private string Conn = null;
        public DbContext ToWriteOrRead(string conn)
        {
            Conn = conn;
            return this;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseLoggerFactory(MyLoggerFactory)
                     //.UseLazyLoadingProxies()
                     .UseSqlServer(Conn);
            }
            optionsBuilder.UseLoggerFactory(MyLoggerFactory);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            #region MyRegion

            {
                //指定主键
                //modelBuilder.Entity().HasKey(a => a.Id);
                /////设置数据库架构
                //modelBuilder.HasDefaultSchema("xl");
                /////表名、属性名映射
                //modelBuilder.Entity().ToTable("UserInfos", "Zhaoxi").Property(p => p.UserAge).HasColumnName("Age");
                ////设置联合主键
                //modelBuilder.Entity().HasKey(p => new { p.SysUserId, p.SysRoleId }); 
                ////初始化数据
                //modelBuilder.Entity().HasData(new List()
                //{
                //});
                ///////表拆分:在数据库中是一整张表,在代码层面是多个实体与其对应;
                //modelBuilder.Entity(dob =>
                //{
                //    dob.ToTable("SysLogInfo");
                //    dob.Property(o => o.LogType).HasColumnName("LogType");//配置两个实体的相同属性映射到表的同一列
                //    dob.HasOne(o => o.SysLogDetail).WithOne().HasForeignKey(o => o.Id); ; //配置两个实体的相同属性映射到表的同一列
                //});
                //modelBuilder.Entity(dob =>
                //{
                //    dob.ToTable("SysLogInfo");
                //    dob.Property(o => o.LogType).HasColumnName("LogType");//配置两个实体的相同属性映射到表的同一列 
                //});
            }

            //设置一对多的关系
            modelBuilder.Entity().HasOne(c => c.Class).WithMany(s => s.Students).HasForeignKey(b => b.ClassId);

            ////多对多关系  
            modelBuilder.Entity(eb =>
            {
                eb.HasOne(p => p.Course).WithMany(u => u.Students).HasForeignKey(u => u.CourseId);
                eb.HasOne(p => p.Student).WithMany(r => r.Courses).HasForeignKey(s => s.StudentId);
            }); 
            modelBuilder.Entity(eb => {
                eb.HasOne(p => p.Course).WithMany(u => u.ClassStudents).HasForeignKey(u => u.CourseId);
                eb.HasOne(p => p.Class).WithMany(r => r.Classs).HasForeignKey(s => s.ClassId);
            });
            #endregion
        }


        public DbSet Classs { get; set; }
        public DbSet Students { get; set; }
        public DbSet Courses { get; set; }
    }
2.FreeSql的流程相对EF就简单许多了,不需要执行“Add-Migration”、“Update-Database”命令,运行时检查没有表自动创建,下面是FreeSql的DbContext类,与EF很相似。
    public class FreeSqlContext: DbContext
    {

        public DbSet Students { get; set; }
        public DbSet Courses { get; set; }
        public DbSet ClassGrades { get; set; }
        public DbSet MiddleClassCourses { get; set; }
        public DbSet MiddleStudentCourses { get; set; }

        //每个 DbContext 只触发一次
        protected override void OnModelCreating(ICodeFirst codefirst)
        {
            codefirst.Entity(eb =>
            {
                eb.HasOne(a => a.Class).HasForeignKey(b => b.ClassId).WithMany(c => c.Students);
            });

            codefirst.Entity(eb =>
            {
                eb.HasOne(a => a.Student).WithMany(t => t.Courses).HasForeignKey(b => b.StudentId);
                eb.HasOne(a => a.Course).WithMany(t => t.Students).HasForeignKey(a => a.CourseId);
            });

            codefirst.Entity(eb =>
            {
                eb.HasOne(a => a.Course).WithMany(t => t.ClassStudents).HasForeignKey(a => a.CourseId);
                eb.HasOne(a => a.Class).WithMany(t => t.Students).HasForeignKey(a => a.ClassId);
            });
        }
    }
3.SqlSuger就更简单了,不需要配置DbContext,配置如下泛型类就可以了,T为实体类
    public class SqlSugerContext: SimpleClient where T : class, new()
    {
        public SqlSugerContext(SqlSugarClient context) : base(context)//注意这里要有默认值等于null
        {
            context.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(T));//这样一个表就能成功创建了
        }
    }
    public class ClassGradeService: SqlSugerContext
    {
        public ClassGradeService(SqlSugarClient context):base(context)
        {

        }
    }
    public class CourseService: SqlSugerContext
    {
        public CourseService(SqlSugarClient context) : base(context)
        {
        }
    }
  public class StudentService: SqlSugerContext
    {
        public StudentService(SqlSugarClient context) : base(context)
        {
        }
    }
  public class MiddleClassCourseCervice : SqlSugerContext
    {
        public MiddleClassCourseCervice(SqlSugarClient context) : base(context)
        {

        }
    }
  public class MiddleStudentCourseService : SqlSugerContext
    {
        public MiddleStudentCourseService(SqlSugarClient context) : base(context)
        {

        }
    }
三:配置声明 1.连接字符串(都实现了读写分离,由于只是测试,数据库主从都是同一个库,实际上不能这样写,不然没有读写分离的意义):
    "EfConnectionStrings": {
        "WriteConnection": "Server=localhost;Database=DbEfCore;Trusted_Connection=True;",
        "ReadConnectionList": [
            "Server=localhost;Database=DbEfCore;Trusted_Connection=True;"
        ]
    },
    "FreeSqlConnectionStrings": "Server=localhost;Database=DbFreeSql;Trusted_Connection=True;",
    "SqlSugerConnectionStrings": "Server=localhost;Database=DbSqlSuger;Trusted_Connection=True;"
2.EF实现读写分离需要自行封装,另外两个只需要配置好连接字符就好了,下面是EF数据库读写分离的实现:
    public enum WriteAndReadEnum
    {
        Write,  //主库操作
        Read  //从库操作
    }
  public interface IDbContextFactory { public EfDbContext ConnWriteOrRead(WriteAndReadEnum writeAndRead); }
public class DBConnectionOption { public string WriteConnection { get; set; } public List ReadConnectionList { get; set; } }
public class DbContextFactory : IDbContextFactory { private readonly EfDbContext _Context = new EfDbContext(); private static int _iSeed = 0; private readonly DBConnectionOption _readAndWrite = null; public DbContextFactory(IOptionsMonitor options) { _readAndWrite = options.CurrentValue; } public EfDbContext ConnWriteOrRead(WriteAndReadEnum writeAndRead) { //判断枚举,不同的枚举可以创建不同的Context 或者更换Context链接; switch (writeAndRead) { case WriteAndReadEnum.Write: ToWrite(); break; //选择链接//更换_Context链接 //选择链接 case WriteAndReadEnum.Read: ToRead(); break; //选择链接//更换_Context链接 default: break; } return _Context; } /// /// 更换成主库连接 /// /// private void ToWrite() { string conn = _readAndWrite.WriteConnection; _Context.ToWriteOrRead(conn); } /// /// 更换成主库连接 /// /// ///策略---数据库查询的负载均衡 /// /// private void ToRead() { var conn = this._readAndWrite.ReadConnectionList[_iSeed++ % this._readAndWrite.ReadConnectionList.Count];//轮询; _Context.ToWriteOrRead(conn); } }
3.在ConfigureServices类中注入:
            #region FreeSql//DbFreeSql
            var freestr = Configuration.GetSection("FreeSqlConnectionStrings").Value;
            IFreeSql fsql = new FreeSql.FreeSqlBuilder()
                 .UseConnectionString(FreeSql.DataType.SqlServer, freestr)
                 .UseSlave(freestr)//使用从数据库,支持多个
                 .UseAutoSyncStructure(true) //自动同步实体结构到数据库
                 .Build(); //请务必定义成 Singleton 单例模式
            services.AddSingleton(fsql);
            services.AddFreeDbContext(options => options.UseFreeSql(fsql));
            #endregion

            #region SqlSuger//DbSqlSuger
            var sugerstr = Configuration.GetSection("SqlSugerConnectionStrings").Value;
            services.AddScoped(options => new SqlSugarClient(new ConnectionConfig()
            {
                ConnectionString = sugerstr,//连接符字串
                DbType = DbType.SqlServer,
                IsAutoCloseConnection = true,
                IniTKEyType = InitKeyType.Attribute,//从特性读取主键自增信息
                SlaveConnectionConfigs = new List() {//使用从数据库,支持多个
                     new SlaveConnectionConfig() { HitRate=10, ConnectionString=sugerstr }
                }
            }));
            services.AddScoped();
            services.AddScoped();
            services.AddScoped();
            services.AddScoped();
            services.AddScoped();
            #endregion

            #region EfCore//DbEfCore
            services.ADDDbContext(options => options.UseSqlServer("name=EfConnectionStrings:WriteConnection"));
            services.Configure(Configuration.GetSection("EfConnectionStrings"));//注入多个链接
            services.AddTransient();
            #endregion
四:总结   到此基本框架就搭建好了,下一篇将分别实现相同功能的三套API进行具体比较。   就目前来说,EF Core 最复杂学习成本高,同时Code First功能也是最强的,SqlSuger最简单容易上手,但是没有严格意义上的Code First,只是能够创建表而已。

.Net 常用ORM框架对比:EF Core、FreeSql、SqlSuger

原文地址:https://www.cnblogs.com/xl-tf/p/14163360.html

您可能感兴趣的文档:

--结束END--

本文标题: .Net 常用ORM框架对比:EF Core、FreeSql、SqlSuger

本文链接: https://www.lsjlt.com/news/8024.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • sql中外码怎么设置
    sql 中外码设置步骤:确定父表和子表。在子表中创建外码列,引用父表主键。使用 foreign key 约束将外码列链接到父表主键。指定引用动作,以处理父表数据更改时的子表数据操作。 ...
    99+
    2024-05-15
  • sql中having是什么
    having 子句用于过滤分组结果,应用于分组后的数据集。它与 where 子句类似,但基于分组结果而不是原始数据。用法:1. 过滤分组后的聚合值。2. 根据分组后的...
    99+
    2024-05-15
  • 在sql中空值用什么表示
    在 sql 中,空值表示未知或不存在的值,可使用 null、空字符串或特殊值表示。处理空值的方法包括使用操作符(is null/is not null)、coalesce 函数(返回第一...
    99+
    2024-05-15
    oracle
  • sql中number什么意思
    sql 中的 number 类型用于存储数值数据,包括小数和整数,特别适合货币、度量和科学数据。其精度由 scale(小数点位数)和 precision(整数字段和小数字段总位数)决定。...
    99+
    2024-05-15
  • sql中空值赋值为0怎么写
    可以通过使用 coalesce() 函数将 sql 中的空值替换为指定值(如 0)。coalesce() 的语法为 coalesce(expression, replacement),其...
    99+
    2024-05-15
  • sql中revoke语句的功能
    revoke 语句用于撤销指定用户或角色的权限或角色成员资格。可撤销的权限包括 select、insert、update、delete 等,撤销的对象类型包括表、视图、存储过程...
    99+
    2024-05-15
    敏感数据
  • sql中REVOKE是什么意思
    revoke 是 sql 中用于撤销用户或角色对数据库对象权限的命令。它通过撤销权限类型、对象级别和目标权限来实现:权限类型:撤销 select、insert、update、d...
    99+
    2024-05-15
  • sql中sp是什么意思
    sql中的sp是存储过程的缩写,它是一种预编译的、已命名的sql语句块,存储在数据库中,可以被用户通过简单命令调用。存储过程的特点有:可重用性、模块化、性能优化、安全性、事务支持。存储过...
    99+
    2024-05-15
    敏感数据
  • sql中references是什么意思
    sql 中的 references 关键字用于在外键约束中定义表之间的父-子关系。外键约束确保子表中的行都引用父表中存在的行,从而维护数据完整性。references 语法的格式为:fo...
    99+
    2024-05-15
  • sql中判断字段为空怎么写
    sql 中可通过 4 种方法判断字段是否为空:1)is null 运算符;2)is not null 运算符;3)coalesce() 函数;4)case 语句。例如,查询所有 colu...
    99+
    2024-05-15
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作