当前位置:首页 > 技术 > 正文内容

Freesql ORM框架核心功能详解与实战应用

访客 技术 2026年7月9日 1

基础配置与连接

首先需要引入必要的NuGet包:

// 核心包和SqlServer驱动包
FreeSql
FreeSql.Provider.SqlServer

初始化数据库连接:

var db = new FreeSqlBuilder()
    .UseConnectionString(DataType.SqlServer, connectionString)
    .UseMonitorCommand(cmd => Console.WriteLine(cmd.CommandText))
    .Build();

启用脏读避免死锁(仅SqlServer):

db.SetGlobalSelectWithLock(SqlServerLock.NoLock, null);

查询操作详解

日期范围查询:

var result = db.Select<Entity>()
    .Where(a => a.CreateTime.Between(startTime, endTime))
    .ToList();

单实体查询:

var item = await db.Select<Song>()
    .Where(a => a.Id == id)
    .ToOneAsync();

自定义SQL查询:

var customResult = db.Ado.Query<CustomDto>(
    "SELECT * FROM Users WHERE Name LIKE @name", 
    new { name = "%keyword%" }
);

排序操作:

var sortedList = db.Select<Topic>()
    .OrderBy(true, "CreatedDate DESC, Id ASC")
    .ToList();

去重查询:

var distinctList = db.Select<Area>()
    .Where(x => x.Type == 1)
    .Distinct()
    .ToList(x => new Area { CityCode = x.CityCode, CityName = x.CityName });

聚合查询:

// 单列聚合
var maxId = db.Select<City>()
    .Where(x => x.Code == "123")
    .Max(x => x.Id);

// 多列聚合
var aggregate = await db.Select<City>()
    .ToAggregateAsync(x => new {
        maxId = x.Max(x.Key.Id),
        count = x.Count(x.Key.CityId),
        sum = x.Sum(x.Key.ProId)
    });

ToSql高级用法

字段别名设置:

var sql1 = db.Select<Topic>()
    .ToSql(a => new { a.Id, a.Title }, FieldAliasOptions.AsProperty);

var sql2 = db.Select<Topic>()
    .ToSql("a.Id AS Id, a.Title AS Title");

复杂查询技术

多表连接:

var joinResult = db.Select<Topic, Category, Type>()
    .LeftJoin((t1, t2, t3) => t1.CategoryId == t2.Id)
    .LeftJoin((t1, t2, t3) => t2.ParentId == t3.Id)
    .Where((t1, t2, t3) => t3.Id > 0)
    .ToList((t1, t2, t3) => new { t1, t2, t3 });

条件表达式:

StatusText = x.Enabled == 1 ? "启用" : "停用"

PlaceText = SqlExt.Case()
    .When(x.Type == 1, "国家")
    .When(x.Type == 2, "地区")
    .Else("街道")
    .End()

分组聚合:

var groupResult = db.Select<City>()
    .GroupBy(x => new { x.CityName, x.Id })
    .ToList(g => new { 
        CityName = g.Key.CityName,
        Id = g.Key.Id,
        Count = g.Count()
    });

表达式拼接:

Expression<Func<Student, bool>> exp1 = x => x.Id == "1";
var exp2 = exp1.And(x => x.Key == "2");
var exp3 = exp1.Or(x => x.Type == "3");

子查询:

var subQuery = db.Select<Province>()
    .Where(x => db.Select<City>()
        .Where(b => b.CityType == 0)
        .ToList(b => b.ProvinceId)
        .Contains(x.Id))
    .ToList();

窗口函数:

var windowResult = db.Select<City>()
    .ToList(x => new {
        all = x,
        RowNum = SqlExt.RowNumber()
            .Over()
            .PartitionBy(x.ProvinceId)
            .OrderBy(x.CityCode)
            .ToValue()
    });

数据操作

插入操作:

[Column(IsPrimary = true, IsIdentity = true)]
public int Id { get; set; }

db.Insert(entity).ExecuteAffrows();
db.Insert(list).IgnoreColumns(x => x.Id).ExecuteAffrows();

删除操作:

db.Delete<Topic>(entity).ExecuteAffrows();
db.Delete<Topic>().Where(s => s.Id == 1).ExecuteAffrows();

更新操作:

// 先查后更
db.Update<Topic>()
    .SetSource(list)
    .IgnoreColumns(a => new { a.Clicks, a.CreateTime })
    .ExecuteAffrows();

// 直接更新
db.Update<Topic>()
    .Set(a => a.Title, "新标题")
    .Where(a => a.Id == 1)
    .ExecuteAffrows();

保存操作:

db.InsertOrUpdate<Entity>()
    .SetSource(list)
    .ExecuteAffrows();

特性配置

// 表结构相关
[Table(Name = "Student")]
[Column(IsPrimary = true)]
[Column(IsIdentity = true)]

// 数据精度
[Column(Precision = 10, Scale = 2)]
[Column(StringLength = 128)]

// 时间戳自动维护
[Column(ServerTime = DateTimeKind.Local, CanUpdate = false)]
public DateTime CreateTime { get; set; }

[Column(ServerTime = DateTimeKind.Local, CanInsert = false)]
public DateTime UpdateTime { get; set; }

过滤器与事务

全局过滤器:

db.GlobalFilter.Apply<UserInfo>("active", x => x.IsActive == true);

var list = db.Select<UserInfo>()
    .DisableGlobalFilter("active")
    .ToList();

事务处理:

using (var uow = db.CreateUnitOfWork()) {
    try {
        uow.GetOrBeginTransaction();
        
        var student = new Student { Name = "张三" };
        uow.Orm.Insert(student).ExecuteAffrows();
        
        uow.Commit();
    } catch (Exception ex) {
        uow.Rollback();
        Console.WriteLine($"操作失败:{ex.Message}");
    }
}

数据迁移

CodeFirst模式:

db.CodeFirst.SyncStructure<EntityType>();

DbFirst模式:

var tables = db.DbFirst.GetTablesByDatabase("databaseName");
var tableInfo = db.DbFirst.GetTableByName("tableName");

性能优化技巧

大批量数据查询分批处理:

static List<List<T>> BatchProcess<T>(List<T> source, int batchSize) {
    var batches = new List<List<T>>();
    for (int i = 0; i < source.Count; i += batchSize) {
        batches.Add(source.GetRange(i, Math.Min(batchSize, source.Count - i)));
    }
    return batches;
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。