Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF核心与GraphQL_C#_Asp.net Core_Entity Framework Core_Graphql_Graphql Dotnet - Fatal编程技术网

C# EF核心与GraphQL

C# EF核心与GraphQL,c#,asp.net-core,entity-framework-core,graphql,graphql-dotnet,C#,Asp.net Core,Entity Framework Core,Graphql,Graphql Dotnet,我目前正在探索GraphQL开发,我目前正在探索通过EF Core生成什么样的SQL查询,我观察到,无论我的GraphQL查询只包含几个字段,EF Core都会为实体的所有字段发送SQL Select 这是我现在使用的代码: public class DoctorType : ObjectGraphType<Doctors> { public DoctorType() { Field(d => d.PrefixTitle);

我目前正在探索GraphQL开发,我目前正在探索通过EF Core生成什么样的SQL查询,我观察到,无论我的GraphQL查询只包含几个字段,EF Core都会为实体的所有字段发送SQL Select

这是我现在使用的代码:

public class DoctorType : ObjectGraphType<Doctors>
{
    public DoctorType()
    {
            Field(d => d.PrefixTitle);
            Field(d => d.FName);
            Field(d => d.MName);
            Field(d => d.LName);
            Field(d => d.SufixTitle);
            Field(d => d.Image);
            Field(d => d.EGN);
            Field(d => d.Description);
            Field(d => d.UID_Code); 
    }
}

public class Doctors : ApplicationUser
{
    public string Image { get; set; }
    [StringLength(50)]
    public string UID_Code { get; set; }
}
生成的SQL选择医生实体的所有字段

是否有任何方法可以进一步优化从EF Core生成的SQL查询

我猜这是因为DoctorType继承自
ObjectGraphType
,而不是医生的某个投影,但我想不出一个聪明的解决方法

有什么建议吗

编辑:

我正在使用Joe McBride版本2.4.0的GraphQL.NET(GraphQL dotnet)

编辑2:

要么我做错了,要么我不知道

作为其中一条建议,我下载了SimonCropp提供的GraphQL.EntityFramework Nuget包

我完成了它所需的所有配置:

        services.AddDbContext<ScheduleDbContext>(options =>
        {
            options.UseMySql(Configuration.GetConnectionString("DefaultConnection"));
        });

        using (var myDataContext = new ScheduleDbContext())
        {
            EfGraphQLConventions.RegisterInContainer(services, myDataContext);
        }
调试日志显示生成的SQL查询是

SELECT `s`.`SpecializationId`, `s`.`Code`, `s`.`SpecializationName`
FROM `Specializations` AS `s`
尽管我只需要specializationName字段,而且我希望它是:

SELECT `s`.`SpecializationName`
FROM `Specializations` AS `s`
更新

我想到目前为止我还不明白graphQL到底是如何工作的。我认为有一些幕后的数据获取,但没有

主提取在查询的字段解析程序中完成:

FieldAsync<ListGraphType<DoctorType>>("doctors", resolve: async ctx => await doctorServices.ListAsync());
专门化类型

 public class SpecializationType : EfObjectGraphType<Specializations>
{
    public SpecializationType(IEfGraphQLService graphQlService
        , IDataLoaderContextAccessor accessor, IDoctorGraphQlServices doctorServices)
        : base(graphQlService)
    {
        Field(p => p.SpecializationId);
        Field(p => p.Code);
        Field(p => p.SpecializationName);
        Field<ListGraphType<DoctorType>, IEnumerable<Doctors>>()
            .Name("doctors")
            .ResolveAsync(ctx =>
            {

                var selectedFields = GraphQLResolverContextHelpers.GetFirstLevelLeavesNamesPascalCase(ctx.SubFields);
                selectedFields = GraphQLResolverContextHelpers.AppendParrentNodeToEachItem(selectedFields, parentNode: "Doctor");
                selectedFields = selectedFields.Union(new[] { "Specializations_SpecializationId" });

                var expression = BuildLinqSelectorObject.BuildSelector<SpecializationsDoctors, SpecializationsDoctors>(selectedFields);

                var doctorsLoader = accessor.Context
                    .GetOrAddCollectionBatchLoader<int, Doctors>(
                        "GetDoctorsBySpecializationId"
                        , (collection, token) =>
                        {
                            return doctorServices.GetDoctorsBySpecializationIdAsync(collection, token, expression);
                        });
                return doctorsLoader.LoadAsync(ctx.Source.SpecializationId);
            });
    }
}
公共类SpecializationType:eObjectGraphType
{
公共专门化类型(IEfGraphQLService graphQlService
,IDataLoaderContextAccessor访问器,IDoctorGraphQlServices博士服务)
:base(graphQlService)
{
字段(p=>p.SpecializationId);
字段(p=>p.Code);
字段(p=>p.SpecializationName);
字段()
.姓名(“医生”)
.ResolveAsync(ctx=>
{
var selectedFields=GraphQLResolverContextHelpers.getFirstLevelLeavesNamePascalCase(ctx.SubFields);
selectedFields=GraphQLResolverContextHelpers.AppendParrentNodeToEachItem(selectedFields,parentNode:“医生”);
selectedFields=selectedFields.Union(新[]{“Specializations\u SpecializationId”});
var expression=BuildLinqSelectorObject.BuildSelector(selectedFields);
var doctorsLoader=accessor.Context
.GetOradCollectionBatchLoader(
“GetDoctorBySpecialization ID”
,(集合、令牌)=>
{
返回doctorServices.GetDoctorsBySpecializationIdAsync(集合、令牌、表达式);
});
返回doctorsLoader.LoadAsync(ctx.Source.SpecializationId);
});
}
}
医生服务:

public class DoctorGraphQlServices : IDoctorGraphQlServices
{
    public ScheduleDbContext _dbContext { get; set; }

    public DoctorGraphQlServices(ScheduleDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<List<Doctors>> ListAsync(int? specializationId = null)
    {
        var doctors = _dbContext.Doctors.AsQueryable();

        if(specializationId != null)
        {
            doctors = doctors.Where(d => d.Specializations.Any(s => s.Specializations_SpecializationId == specializationId));
        }

        return await doctors.ToListAsync();
    }

    public async Task<ILookup<int, Doctors>> GetDoctorsBySpecializationIdAsync(IEnumerable<int> specializationIds, CancellationToken token, Expression<Func<SpecializationsDoctors, SpecializationsDoctors>> selector = null)
    {
        var doctors = await _dbContext.SpecializationsDoctors
            .Include(s => s.Doctor)
            .Where(spDocs => specializationIds.Any(sp => sp == spDocs.Specializations_SpecializationId))
            .Select(selector: selector)
            .ToListAsync();

        return doctors.ToLookup(i => i.Specializations_SpecializationId, i => i.Doctor);
    }

}
公共类DoctorGraphQlServices:IDoctorGraphQlServices
{
公共ScheduleDbContext _dbContext{get;set;}
公共DoctorGraphQlServices(ScheduleDbContext-dbContext)
{
_dbContext=dbContext;
}
公共异步任务ListAsync(int?specializationId=null)
{
var doctors=_dbContext.doctors.AsQueryable();
if(specializationId!=null)
{
医生=医生。其中(d=>d.Specializations.Any(s=>s.Specializations\U SpecializationId==SpecializationId));
}
返回等待医生。ToListSync();
}
公共异步任务GetDoctorBySpecializationIDASync(IEnumerable SpecializationId、CancellationToken令牌、表达式选择器=null)
{
var医生=等待_dbContext.SpecializationsDoctors
.包括(s=>s.Doctor)
.Where(spDocs=>SpecializationId.Any(sp=>sp==spDocs.Specializations\U SpecializationId))
.选择(选择器:选择器)
.ToListAsync();
返回documents.ToLookup(i=>i.Specializations\u SpecializationId,i=>i.Doctor);
}
}
专业服务

public class SpeciaizationGraphQlServices : ISpecializationGraphQlServices
{

    public ScheduleDbContext _dbContext { get; set; }

    public SpeciaizationGraphQlServices(ScheduleDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<dynamic> ListAsync(string doctorId = null, Expression<Func<Specializations, Specializations>> selector = null)
    {
        var specializations = _dbContext.Specializations.AsQueryable();

        if (!string.IsNullOrEmpty(doctorId))
        {
            specializations = specializations.Where(s => s.Doctors.Any(d => d.Doctors_Id == doctorId));
        }

        return await specializations.Select(selector).ToListAsync();

    }

    public async Task<ILookup<string, Specializations>> GetSpecializationsByDoctorIdAsync(IEnumerable<string> doctorIds, CancellationToken token)
    {
        var specializations = await _dbContext.SpecializationsDoctors
            .Include(s => s.Specialization)
            .Where(spDocs => doctorIds.Any(sp => sp == spDocs.Doctors_Id))
            .ToListAsync();

        return specializations.ToLookup(i => i.Doctors_Id, i => i.Specialization);
    }

    public IQueryable<Specializations> List(string doctorId = null)
    {
        var specializations = _dbContext.Specializations.AsQueryable();

        if (!string.IsNullOrEmpty(doctorId))
        {
            specializations = specializations.Where(s => s.Doctors.Any(d => d.Doctors_Id == doctorId));
        }

        return specializations;
    }
}
公共类SpecializationGraphQlServices:isSpecializationGraphQlServices
{
公共ScheduleDbContext _dbContext{get;set;}
公共SpecializationGraphQLServices(ScheduleDbContext dbContext)
{
_dbContext=dbContext;
}
公共异步任务ListAsync(字符串doctorId=null,表达式选择器=null)
{
var specializations=_dbContext.specializations.AsQueryable();
如果(!string.IsNullOrEmpty(doctorId))
{
专科=专科。其中(s=>s.Doctors.Any(d=>d.Doctors\u Id==doctorId));
}
return wait specializations.Select(选择器).toListSync();
}
公共异步任务GetSpecializationsByDoctorIdAsync(IEnumerable doctorIds,CancellationToken token)
{
var specializations=await\u dbContext.SpecializationsDoctors
.包括(s=>s.专业化)
.Where(spDocs=>doctorIds.Any(sp=>sp==spDocs.Doctors\u Id))
.ToListAsync();
返回specializations.ToLookup(i=>i.Doctors\u Id,i=>i.Specialization);
}
公共IQueryable列表(字符串doctorId=null)
{
var specializations=_dbContext.specializations.AsQueryable();
如果(!string.IsNullOrEmpty(doctorId))
{
专科=专科。其中(s=>s.Doctors.Any(d=>d.Doctors\u Id==doctorId));
}
返回专业化;
}
}

这篇文章已经变得相当大,很抱歉出现了span..

对于
DoctorType
,请检查定义的
ObjectGraphType
,它用于返回
Doctors

例如,我有如下
PlayerType

public class PlayerType : ObjectGraphType<Player>
{
    public PlayerType(ISkaterStatisticRepository skaterStatisticRepository)
    {
        Field(x => x.Id);
        Field(x => x.Name, true);
        Field(x => x.BirthPlace);
        Field(x => x.Height);
        Field(x => x.WeightLbs);
        Field<StringGraphType>("birthDate", resolve: context => context.Source.BirthDate.ToShortDateString());
        Field<ListGraphType<SkaterStatisticType>>("skaterSeasonStats",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context => skaterStatisticRepository.Get(context.Source.Id), description: "Player's skater stats");
    }
}
公共类PlayerType:ObjectGraphType
{
公共播放器类型(ISkaterStatisticRepository skaterStatisticRepository)
{
字段(x=>x.Id);
字段(x=>x.Name,true);
字段(x=>x.出生地);
字段(x=>x.Height);
字段(x=>x.WeightLbs);
字段(“生日”,解析:上下文=>
    public class RootQuery : EfObjectGraphType
{
    public RootQuery(IEfGraphQLService efGraphQlService, ISpecializationGraphQlServices specializationServices,
        IDoctorGraphQlServices doctorServices, ScheduleDbContext dbContext) : base(efGraphQlService)
    {
        Name = "Query";

        FieldAsync<ListGraphType<SpecializationType>>("specializations"
            , resolve: async ctx => {

                var selectedFields = GraphQLResolverContextHelpers.GetFirstLevelLeavesNamesPascalCase(ctx.SubFields);
                var expression = BuildLinqSelectorObject.DynamicSelectGenerator<Specializations>(selectedFields.ToArray());

                return await specializationServices.ListAsync(selector: expression);
            });
    }
}
 public class SpecializationType : EfObjectGraphType<Specializations>
{
    public SpecializationType(IEfGraphQLService graphQlService
        , IDataLoaderContextAccessor accessor, IDoctorGraphQlServices doctorServices)
        : base(graphQlService)
    {
        Field(p => p.SpecializationId);
        Field(p => p.Code);
        Field(p => p.SpecializationName);
        Field<ListGraphType<DoctorType>, IEnumerable<Doctors>>()
            .Name("doctors")
            .ResolveAsync(ctx =>
            {

                var selectedFields = GraphQLResolverContextHelpers.GetFirstLevelLeavesNamesPascalCase(ctx.SubFields);
                selectedFields = GraphQLResolverContextHelpers.AppendParrentNodeToEachItem(selectedFields, parentNode: "Doctor");
                selectedFields = selectedFields.Union(new[] { "Specializations_SpecializationId" });

                var expression = BuildLinqSelectorObject.BuildSelector<SpecializationsDoctors, SpecializationsDoctors>(selectedFields);

                var doctorsLoader = accessor.Context
                    .GetOrAddCollectionBatchLoader<int, Doctors>(
                        "GetDoctorsBySpecializationId"
                        , (collection, token) =>
                        {
                            return doctorServices.GetDoctorsBySpecializationIdAsync(collection, token, expression);
                        });
                return doctorsLoader.LoadAsync(ctx.Source.SpecializationId);
            });
    }
}
public class DoctorGraphQlServices : IDoctorGraphQlServices
{
    public ScheduleDbContext _dbContext { get; set; }

    public DoctorGraphQlServices(ScheduleDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<List<Doctors>> ListAsync(int? specializationId = null)
    {
        var doctors = _dbContext.Doctors.AsQueryable();

        if(specializationId != null)
        {
            doctors = doctors.Where(d => d.Specializations.Any(s => s.Specializations_SpecializationId == specializationId));
        }

        return await doctors.ToListAsync();
    }

    public async Task<ILookup<int, Doctors>> GetDoctorsBySpecializationIdAsync(IEnumerable<int> specializationIds, CancellationToken token, Expression<Func<SpecializationsDoctors, SpecializationsDoctors>> selector = null)
    {
        var doctors = await _dbContext.SpecializationsDoctors
            .Include(s => s.Doctor)
            .Where(spDocs => specializationIds.Any(sp => sp == spDocs.Specializations_SpecializationId))
            .Select(selector: selector)
            .ToListAsync();

        return doctors.ToLookup(i => i.Specializations_SpecializationId, i => i.Doctor);
    }

}
public class SpeciaizationGraphQlServices : ISpecializationGraphQlServices
{

    public ScheduleDbContext _dbContext { get; set; }

    public SpeciaizationGraphQlServices(ScheduleDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<dynamic> ListAsync(string doctorId = null, Expression<Func<Specializations, Specializations>> selector = null)
    {
        var specializations = _dbContext.Specializations.AsQueryable();

        if (!string.IsNullOrEmpty(doctorId))
        {
            specializations = specializations.Where(s => s.Doctors.Any(d => d.Doctors_Id == doctorId));
        }

        return await specializations.Select(selector).ToListAsync();

    }

    public async Task<ILookup<string, Specializations>> GetSpecializationsByDoctorIdAsync(IEnumerable<string> doctorIds, CancellationToken token)
    {
        var specializations = await _dbContext.SpecializationsDoctors
            .Include(s => s.Specialization)
            .Where(spDocs => doctorIds.Any(sp => sp == spDocs.Doctors_Id))
            .ToListAsync();

        return specializations.ToLookup(i => i.Doctors_Id, i => i.Specialization);
    }

    public IQueryable<Specializations> List(string doctorId = null)
    {
        var specializations = _dbContext.Specializations.AsQueryable();

        if (!string.IsNullOrEmpty(doctorId))
        {
            specializations = specializations.Where(s => s.Doctors.Any(d => d.Doctors_Id == doctorId));
        }

        return specializations;
    }
}
public class PlayerType : ObjectGraphType<Player>
{
    public PlayerType(ISkaterStatisticRepository skaterStatisticRepository)
    {
        Field(x => x.Id);
        Field(x => x.Name, true);
        Field(x => x.BirthPlace);
        Field(x => x.Height);
        Field(x => x.WeightLbs);
        Field<StringGraphType>("birthDate", resolve: context => context.Source.BirthDate.ToShortDateString());
        Field<ListGraphType<SkaterStatisticType>>("skaterSeasonStats",
            arguments: new QueryArguments(new QueryArgument<IntGraphType> { Name = "id" }),
            resolve: context => skaterStatisticRepository.Get(context.Source.Id), description: "Player's skater stats");
    }
}
public class NHLStatsQuery : ObjectGraphType
{
    public NHLStatsQuery(IPlayerRepository playerRepository, NHLStatsContext dbContext)
    {
        Field<ListGraphType<PlayerType>>(
            "players",
            resolve: context => {
                return dbContext.Players.Select(p =>new Player { Id = p.Id, Name = p.Name });
                //return playerRepository.All();
            });
    }
}