实现 EF Core 6 自定义查询标记
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现 EF Core 6 自定义查询标记相关的知识,希望对你有一定的参考价值。
前言
在《EF Core使用Simple Logging输出日志》中,我们介绍了查询标记 TagWith
,它可以帮助我们快速定位到需要的日志:
而在 .NET 6 中,新增了另外一个查询标记 TagWithCallSite
,它可以标记出代码的位置:
var user = await new DefaultDbContext().User
.Where(p => p.Name == "My IO")
.TagWith("Find My IO")
.TagWithCallSite()
.FirstOrDefaultAsync();
那它是怎么做到的呢?
原理探究
查看 TagWithCallSite
的源代码:
public static IQueryable<T> TagWithCallSite<T>(
this IQueryable<T> source,
[NotParameterized] [CallerFilePath] string? filePath = null,
[NotParameterized] [CallerLineNumber] int lineNumber = 0)
原来,它使用了 CallerFilePathAttribute
和 CallerLineNumberAttribute
来获取包含调用方的源文件完整路径和调用方法的行号。
原理利用
这让我们想到了,在《.NET 6新特性试用 | ArgumentNullException卫语句》中发现的 CallerArgumentExpressionAttribute
,它可以获取执行的表达式。
通过添加此 Attribute,我们可以创建自己的自定义查询标记。实现代码如下:
public static IQueryable<T> TagWithCallInfo<T>(this IQueryable<T> source,
string? tag = null,
[NotParameterized][CallerArgumentExpression("source")] string? argument = null,
[NotParameterized][CallerMemberName] string? memberName = null,
[NotParameterized][CallerFilePath] string? filePath = null,
[NotParameterized][CallerLineNumber] int lineNumber = 0)
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine(tag);
foreach (var str in argument.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries))
stringBuilder.AppendLine(str);
stringBuilder.AppendLine($@"at memberName");
stringBuilder.AppendLine($@"File: filePath:lineNumber");
return source.TagWith(stringBuilder.ToString());
该方法不仅包含自定义标记文本,还自动包括了被调用的 LINQ 查询表达式、方法名称、文件路径、行号。
Demo
运行下列代码进行验证,完全满足了我们的要求:
var user = await new DefaultDbContext().User
.Where(p => p.Name == "My IO")
.TagWithCallInfo("Find My IO")
.FirstOrDefaultAsync();
结论
今天,通过扩展 TagWithCallSite
,我们实现了自定义查询标记。
添加微信号【MyIO666】,邀你加入技术交流群
以上是关于实现 EF Core 6 自定义查询标记的主要内容,如果未能解决你的问题,请参考以下文章
如何在 EF Core 5 中为自定义 SQL 配置导航属性
我可以重用代码来为 EF Core 的子属性选择自定义 DTO 对象吗?
EF core (code first) 通过自定义 Migration History 实现多租户使用同一数据库时更新数据库结构