浅讲EF高级用法之自定义函数
介绍
好久没给大家更新文章了,前2个月因家庭原因回到青岛,比较忙所以没有什么时间给大家更新知识分享,这2个月在和同事一起做项目,发现了很多好意思的东西拿出来给大家讲一讲。
正文
大家先来下面这幅图,这是我司一个老项目的代码,你可能会好奇为啥给我看SQL说好的讲EF哪?

大家看这个我框出来的部分,这里调用了一个SQL的函数,虽然我们都在使用EF的过程中每天喊着不要使用存储过程、函数、触发器等SQL相关的东西,但是其实真实落地到体积足够庞大的项目后,
我们会发现,很多东西不是我们能够左右的。当客户执意一些东西的时候我们只能想办法设计的更好,当然上面的图是一个错误的写法。
这个项目中有很多实体的查询、添加、修改需要调用加密、解密函数,所以这部分代码都采用原生SQL来做的,这非常破坏我们项目整体的代码结构。
其实EF本身是支持我们调用SQL函数的。
现在就给大家上代码
首先新建3个实体
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public int? Rating { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int Rating { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
public List<Comment> Comments { get; set; }
}
public class Comment
{
public int CommentId { get; set; }
public string Text { get; set; }
public int Likes { get; set; }
public int PostId { get; set; }
public Post Post { get; set; }
}
public class ApplicationDbContext : DbContext
{
public DbSet<Blog> Blog { get; set; }
public DbSet<Post> Post { get; set; }
public DbSet<Comment> Comment { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Blog>()
.HasMany(b => b.Posts)
.WithOne(p => p.Blog);
modelBuilder.Entity<Post>()
.HasMany(p => p.Comments)
.WithOne(c => c.Post);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFCoreDbFunction.Disconnected;Trusted_Connection=True;ConnectRetryCount=0");
}
}
将方法映射到自定义 SQL
先创建一个自定义函数
CREATE FUNCTION dbo.CommentedPostCountForBlog(@id int)
RETURNS int
AS
BEGIN
RETURN (SELECT COUNT(*)
FROM [Post] AS [p]
WHERE ([p].[BlogId] = @id) AND ((
SELECT COUNT(*)
FROM [Comment] AS [c]
WHERE [p].[PostId] = [c].[PostId]) > 0));
END
然后在DbContext中新增下面代码,
// CLR 方法的主体并不重要。 不会在客户端调用此方法,除非 EF Core 不能转换其参数。 如果可以转换参数,EF Core 只关心方法签名。
public int ActivePostCountForBlog(int blogId)
=> throw new NotSupportedException();
// 此函数定义现在可以与模型配置中用户定义的函数关联
modelBuilder.HasDbFunction(typeof(BloggingContext).GetMethod(nameof(ActivePostCountForBlog), new[] { typeof(int) }))
.HasName("CommentedPostCountForBlog");
我们执行下面代码
var query1 = from b in context.Blogs
where context.ActivePostCountForBlog(b.BlogId) > 1
select b;
// 对应SQL语句
SELECT [b].[BlogId], [b].[Rating], [b].[Url]
FROM [Blogs] AS [b]
WHERE [dbo].[CommentedPostCountForBlog]([b].[BlogId]) > 1
将可查询函数映射到表值函数
CREATE FUNCTION dbo.PostsWithPopularComments(@likeThreshold int)
RETURNS TABLE
AS
RETURN
(
SELECT [p].[PostId], [p].[BlogId], [p].[Content], [p].[Rating], [p].[Title]
FROM [Posts] AS [p]
WHERE (
SELECT COUNT(*)
FROM [Comments] AS [c]
WHERE ([p].[PostId] = [c].[PostId]) AND ([c].[Likes] >= @likeThreshold)) > 0
)
public IQueryable<Post> PostsWithPopularComments(int likeThreshold)
=> FromExpression(() => PostsWithPopularComments(likeThreshold));
modelBuilder.HasDbFunction(typeof(BloggingContext).GetMethod(nameof(PostsWithPopularComments), new[] { typeof(int) }));
执行下面代码
var likeThreshold = 3;
var query1 = from p in context.PostsWithPopularComments(likeThreshold)
orderby p.Rating
select p;
// 对应SQL语句
SELECT [p].[PostId], [p].[BlogId], [p].[Content], [p].[Rating], [p].[Title]
FROM [dbo].[PostsWithPopularComments](@likeThreshold) AS [p]
ORDER BY [p].[Rating]
结语
最后欢迎各位读者关注我的博客, https://github.com/MrChuJiu/Dppt 欢迎大家Star
联系作者:加群:867095512 @MrChuJiu
浅讲EF高级用法之自定义函数的更多相关文章
- [iOS]C语言技术视频-15-指针变量高级用法练习一(函数指针完成动态排序)
下载地址: 链接: http://pan.baidu.com/s/1o6MOzX4 密码: xzxn
- Bash 脚本编程的一些高级用法
概述 偶然间发现 man bash 上其实详细讲解了 shell 编程的语法,包括一些很少用却很实用的高级语法.就像发现了宝藏的孩子,兴奋莫名.于是参考man bash,结合自己的理解,整理出了这篇文 ...
- Python 内置函数sorted()在高级用法
对于Python内置函数sorted(),先拿来跟list(列表)中的成员函数list.sort()进行下对比.在本质上,list的排序和内建函数sorted的排序是差不多的,连参数都基本上是一样的. ...
- makefile高级用法--使用函数
makefile高级用法--使用函数 分类: C/C++ 使用函数 ———— 在Makefile中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能.make所支持的函数也不算很多, ...
- Python函数装饰器高级用法
在了解了Python函数装饰器基础知识和闭包之后,开始正式学习函数装饰器. 典型的函数装饰器 以下示例定义了一个装饰器,输出函数的运行时间: 函数装饰器和闭包紧密结合,入参func代表被装饰函数,通过 ...
- 浅谈Excel开发:六 Excel 异步自定义函数
上文介绍了Excel中的自定义函数(UDF ),它极大地扩展了Excel插件的功能,使得我们可以将业务逻辑以Excel函数的形式表示,并可以根据这些细粒度的自定义函数,构建各种复杂的分析报表. 普通的 ...
- 浅谈Excel开发:四 Excel 自定义函数
我们知道,Excel中有很多内置的函数,比如求和,求平均,字符串操作函数,金融函数等等.在有些时候,结合业务要求,这些函数可能不能满足我们的需求,比如我想要一个函数能够从WebService上获取某只 ...
- Newtonsoft.Json高级用法 1.忽略某些属性 2.默认值的处理 3.空值的处理 4.支持非公共成员 5.日期处理 6.自定义序列化的字段名称
手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口多次修改中,实体添加了很多字段用于中间计算或者存储,然后最终用Newtonsoft.Json进行序列化返回数 ...
- MySQL自定义函数用法详解-复合结构自定义变量/流程控制
自定义函数 (user-defined function UDF)就是用一个象ABS() 或 CONCAT()这样的固有(内建)函数一样作用的新函数去扩展MySQL. 所以UDF是对MySQL功能的一 ...
随机推荐
- MySQL查询数据库表空间大小
一.查询所有数据库占用空间大小 SELECT TABLE_SCHEMA, CONCAT( TRUNCATE(SUM(data_length) / 1024 / 1024, 2), ' MB' ) AS ...
- KNN分类
1. KNN简介 K近邻(K-Nearest Neighbor)简称KNN.它可以做分类算法,也可以做回归算法.个人经验:KNN在做分类问题时非常有效. 2. KNN算法思想 在样本空间中,我们认为两 ...
- 2020腾讯犀牛鸟网络安全T-Star高校挑战赛writeup
签到 浏览器禁用js,在www目录下有 key 命令执行基础 使用 | 可以执行其他命令,在 ../目录下有 key.php cat 一下读出来 你能爆破吗 一开始随便输了个账号的时候不是这个页面,抓 ...
- 删除空行(嵌套)(Power Query 之 M 语言)
数据源: "姓名""基数""个人比例""个人缴纳""公司比例""公司缴纳"&qu ...
- Table.Combine追加…Combine(Power Query 之 M 语言)
数据源: 销量表和部门表 目标: 其中一表的数据追加到另一表后面,相同列直接追加,不同列增加新列 操作过程: 选取销量表>[主页]>[追加查询]/[将查询追加为新查询]>选择要追加的 ...
- freeswitch APR-UTIL库消息队列实现
概述 freeswitch的核心源代码是基于apr库开发的,在不同的系统上有很好的移植性. APR库在之前的文章中已经介绍过了,APR-UTIL库是和APR并列的工具库,它们都是由APACHE开源出来 ...
- LuoguP7398 [COCI2020-2021#5] Šifra 题解
Content 给定一个长度 \(n\) 的只包含小写字母和 \(0\sim9\) 的字符串(字符串中的字母可视为分隔符).求字符串中包含多少个不同的数字. 数据范围:\(1\leqslant n\l ...
- mysql 禁止自动提交设置
mysql禁止自动提交的设置, 在my.ini文件里加上如下的一句便可 init_connect='SET autocommit=0' 但是有个问题,对root用户进行autocommit变量的查询, ...
- JAVA使用itext根据模板生成PDF文档
1.制作PDF模板 网址打开:https://www.pdfescape.com/open/ 我们这里先在线上把基础的内容用word文档做好,然后转成PDF模板,直接上传到网站上,这样方便点 假设我们 ...
- fedora之自动寻找命令并提示安装PackageKit-command-not-found
fedora 1.比如,我要用clang 命令编译代码,但是没有该指令.比如: clang main.cxx -o main 2.那么,输入未知命令,希望fedora会自动寻找相对应的包,再并提示安装 ...