我正在使用 EF Core 3 for .NET Standard 2.0 编写 POCO 生成器库。该库将用于通过 .NET Framework 和 .NET Core 项目中的 T4 模板生成
.cs
文件。
我创建了一个包装类,用于存储所有典型 LINQ 查询的静态函数,例如
.Where
、.FirstOrDefault
等。
这是一个例子:
public abstract class QueryableTable<T> where T : QueryableTable<T>, new()
{
public static Func<DatabaseContext, bool, IQueryable<T>> QueryInitializer;
public static List<T> Where(Expression<Func<T, bool>> predicate, bool eagerLoad = false)
{
using (var context = new DatabaseContext())
{
return QueryInitializer(context, eagerLoad).Where(predicate).ToList();
}
}
}
现在在我的模型中,我使用静态构造函数来初始化
QueryInitializer
内的 QueryableTable
,如下所示:
[Table("comment")]
public class Comment : QueryableTable<Comment>
{
[Key]
public int Id { get; set; }
public int PersonId { get; set; }
// Navigation property
public Person Person { get; set; }
static Comment()
{
QueryableTable<Comment>.QueryInitializer = (context, eagerLoad) =>
{
return eagerLoad ?
context.Set<Comment>().Include(t => t.Person) as IQueryable<Comment> :
context.Set<Comment>();
};
}
}
如果我在通过
Comment
访问抽象类之前调用静态 Comment.Where(t => t.Id == 1)
构造函数,则此方法有效。
但是,如果我立即调用它而不首先调用静态
Comment
构造函数,则会如预期的那样在 QueryInitializer
上收到空引用异常。
这一切都是有道理的,但我首先试图找出一种在静态方法之前调用静态构造函数的优雅方法,其次我试图说服自己,虽然这种设计在实践中很有用,因为通过静态
Class.Where()
方法进行查询很简单,将这些方法设为静态感觉不太好。
我通过在
QueryInitializer
周围制作一个包装器来解决这个问题,该包装器创建 T
的新实例,并立即将其丢弃以便垃圾处理来清理。但是,它确实调用了 Comment
的静态构造函数,它执行了我想要的操作。它的设计不是最干净的,但它运行良好并且完全独立。
protected static IQueryable<T> GetQueryStart(DatabaseContext context, bool eagerLoading)
{
if (QueryInitializer == null)
{
new T();
{
return QueryInitializer(context, eagerLoading);
}