Entity framework core 在DbContext级别添加include

Entity framework core 在DbContext级别添加include,entity-framework-core,Entity Framework Core,我想实现类似于延迟加载的东西,但不知道如何实现。我想强制实体框架核心包含实现我的接口的类型的所有查询的导航属性 public interface IMustHaveOrganisation { Guid OrganisationId { get; set; } Organisation Organisation { get; set; } } public class MyEntity : IMustHaveOrganisation { public Guid Orga

我想实现类似于延迟加载的东西,但不知道如何实现。我想强制实体框架核心包含实现我的接口的类型的所有查询的导航属性

public interface IMustHaveOrganisation
{
    Guid OrganisationId { get; set; }
    Organisation Organisation { get; set; }
}

public class MyEntity : IMustHaveOrganisation {
    public Guid OrganisationId { get; set; }
    public virtual Organisation Organisation { get; set; }
}
如果没有延迟加载,我需要在每个查询中添加.Include(x=>x.organization),而且我不能使用微软提供的延迟加载实现。我需要一种只加载一个属性的自定义实现。 甚至强迫DbContext以某种方式包含该属性,这对我来说也很好


如何实现这一点?

在表达式树被EF Core翻译之前,您可以通过重写表达式树来实现这一点

为了在某种程度上实现这一点,您不必在查询中指定任何其他内容,您可以挂接到查询管道的最开始部分,并根据需要插入
Include()
调用

这可以通过指定自定义
iQueryTranslationPreprocessFactory
实现来实现

以下完全工作的控制台项目演示了此方法:

使用系统诊断;
使用System.Linq;
使用System.Linq.Expressions;
使用Microsoft.EntityFrameworkCore;
使用Microsoft.EntityFrameworkCore.Query;
使用Microsoft.Extensions.DependencyInjection;
使用Microsoft.Extensions.Logging;
命名空间IssueConsoleTemplate
{
公营班级组织
{
公共int组织ID{get;set;}
公共字符串名称{get;set;}
}
公共界面必须是一个组织
{
int OrganizationID{get;set;}
组织{get;set;}
}
公共类实体:我必须有一个组织
{
公共int MyEntityId{get;set;}
公共字符串名称{get;set;}
公共int组织ID{get;set;}
公共虚拟组织{get;set;}
}
公共类CustomQueryTranslationPreprocessFactory:IQueryTranslationPreprocessFactory
{
私有只读QueryTranslationPreprocessDependencies依赖项;
私有只读RelationalQueryTranslationPreprocessDependencies\u relationalDependencies;
公共CustomQueryTranslationPreprocessFactory(
QueryTranslationPreprocessorDependencies依赖项,
RelationalQueryTranslationPreprocessOrdependences(关系依赖项)
{
_依赖关系=依赖关系;
_relationalDependencies=relationalDependencies;
}
公共虚拟QueryTranslationPreprocessor创建(QueryCompilationContext QueryCompilationContext)
=>新的CustomQueryTranslationPreprocessor(_dependencies,_relationalDependencies,queryCompilationContext);
}
公共类CustomQueryTranslationPreprocessor:RelationalQueryTranslationPreprocessor
{
公共CustomQueryTranslationPreprocessor(
QueryTranslationPreprocessorDependencies依赖项,
RelationalQueryTranslationPreprocessOrdependences RelationalDependences,
QueryCompilationContext查询compilationcontext)
:base(依赖项、关系依赖项、queryCompilationContext)
{
}
公共重写表达式过程(表达式查询)
{
query=新的依赖项包括ExpressionVisitor()。访问(查询);
返回基处理(查询);
}
}
公共类依赖项包括ExpressionVisitor:ExpressionVisitor
{
受保护的重写表达式VisitConstant(ConstantExpression节点)
{
//如果某个实体处于
//DbSet实现imusthaveorganization。
如果(node.Type.IsGenericType&&
node.Type.GetGenericTypeDefinition()==typeof(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable)&&
node.Type.GenericTypeArguments.Length==1&&
typeof(imusthaveOrganization).IsAssignableFrom(node.Type.GenericTypeArguments[0]))
{
返回表达式。调用(
类型(EntityFrameworkQueryableExtensions),
名称(EntityFrameworkQueryableExtensions.Include),
新[]{node.Type.GenericTypeArguments[0]},
base.VisitConstant(节点),
表达式.常量(名称(imusthaveorganization.organization));
}
返回base.VisitConstant(节点);
}
}
公共类上下文:DbContext
{
公共DbSet myenties{get;set;}
公共数据库集组织{get;set;}
配置时受保护的覆盖无效(DBContextOptions Builder Options Builder)
{
//注册自定义iQueryTranslationPreprocessFactory实现。
//由于这是一个控制台程序,我们需要创建自己的
//此服务的ServiceCollection。
//在ASP.NET核心应用程序中,可以将AddSingleton调用添加到
//一般服务配置方法。
var serviceProvider=newservicecolection()
.AddEntityFrameworkSqlServer()
.AddSingleton()
.AddScope(
s=>LoggerFactory.Create(
b=>b
.AddConsole()
.AddFilter(level=>level>=LogLevel.Information)))
.BuildServiceProvider();
选项生成器
.UseInternalServiceProvider(serviceProvider)//
{
entity.HasData(
新MyEntity{MyEntityId=1,Name=“第一个实体”,OrganizationId=1},
新MyEntity{MyEntityId=2,Name=“第二个实体”,OrganizationId=1},
新MyEntity{MyEntityId=3,Name=“第三实体”,OrganizationId=2});