【发布时间】:2020-01-26 14:28:49
【问题描述】:
我面临的问题不是很典型,因为我正在尝试以某种方式制作通用的 graphql Web api。我根据我在互联网上找到的一些文章解决了我的问题,这些文章我根据自己的需要进行了重构。问题是我正在基于数据库元数据制作一个 graphql api,我已经设法创建了一个根查询,尽管现在的问题在于类型。工作流程本质上是循环遍历包含表名和列的集合,并将它们添加到类型/字段中。然而问题是,当我想说查询子列表时,我没有来自其他类型的子字段。
本质上:
query getCategoriesAndRelatedProducts {
categories {
categoryId
productList {
//productList got no fields
}
}
}
我没有像这样从模型到 GraphType 进行法线映射
public class ProductObject : ObjectGraphType<Product>
{
private readonly IProductService product;
public ProductObject(IProductService p)
{
product = p;
Field(f => f.Id);
Field(f => f.Name);
FieldAsync<ProductTypeObject>("type",
resolve: async context => await product.GetProductType(context.Source.Id));
}
}
我的根查询是以这种方式完成的
public class NorthWindQuery : ObjectGraphType<object>
{
private readonly NorthWindContext _dbContext;
private IDatabaseMetadata _dbMetadata;
private ITableNameLookup _tableNameLookup;
public NorthWindQuery(NorthWindContext dbContext, IDatabaseMetadata dbMetadata,
ITableNameLookup tableNameLookup)
{
_dbMetadata = dbMetadata;
_tableNameLookup = tableNameLookup;
_dbContext = dbContext;
foreach (var metaTable in _dbMetadata.GetTableMetadatas())
{
var tableType = new TableType(metaTable);
var friendlyTableName = _tableNameLookup.GetFriendlyName(metaTable.TableName);
AddField(new FieldType
{
Name = friendlyTableName,
Type = tableType.GetType(),
ResolvedType = tableType,
Resolver = new MyFieldResolver(metaTable, _dbContext),
Arguments = new QueryArguments(
tableType.TableArgs
)
});
// lets add key to get list of current table
var listType = new ListGraphType(tableType);
AddField(new FieldType
{
Name = $"{friendlyTableName}_list",
Type = listType.GetType(),
ResolvedType = listType,
Resolver = new MyFieldResolver(metaTable, _dbContext),
Arguments = new QueryArguments(
tableType.TableArgs
)
});
}
TableType 是这样完成的:
public class TableType : ObjectGraphType<object>
{
public TableType (TableMetadata tableMetadata)
{
Name = tableMetadata.TableName;
foreach (var tableColumn in tableMetadata.Columns)
{
InitGraphTableColumn(tableColumn);
}
TableArgs.Add(new QueryArgument<IdGraphType> { Name = "id" });
TableArgs.Add(new QueryArgument<IntGraphType> { Name = "first" });
TableArgs.Add(new QueryArgument<IntGraphType> { Name = "offset" });
TableArgs.Add(new QueryArgument<StringGraphType> { Name = "includes" });
}
public QueryArguments TableArgs
{
get; set;
}
private IDictionary<string, Type> _databaseTypeToSystemType;
protected IDictionary<string, Type> DatabaseTypeToSystemType
{
get
{
if (_databaseTypeToSystemType == null)
{
_databaseTypeToSystemType = new Dictionary<string, Type>
{
{ "uniqueidentifier", typeof(String) },
{ "char", typeof(String) },
{ "nvarchar", typeof(String) },
{ "int", typeof(int) },
{ "decimal", typeof(decimal) },
{ "bit", typeof(bool) }
};
}
return _databaseTypeToSystemType;
}
}
private void InitGraphTableColumn(ColumnMetadata columnMetadata)
{
var graphQLType = ResolveColumnMetaType(columnMetadata.DataType).GetGraphTypeFromType(true);
var columnField = Field(
graphQLType,
columnMetadata.ColumnName
);
columnField.Resolver = new NameFieldResolver();
FillArgs(columnMetadata.ColumnName);
}
private void FillArgs(string columnName)
{
if(TableArgs == null)
{
TableArgs = new QueryArguments(
new QueryArgument<StringGraphType>()
{
Name = columnName
});
}
else
{
TableArgs.Add(new QueryArgument<StringGraphType> { Name = columnName });
}
}
private Type ResolveColumnMetaType(string dbType)
{
if (DatabaseTypeToSystemType.ContainsKey(dbType))
return DatabaseTypeToSystemType[dbType];
return typeof(String);
}
基于我只有 1 个 tableType 和 2 个解析器,tableType 是构造类型的类,a 和 2 个解析器用于将 graphql 转换为查询并返回 NameFieldResolver 的值,MyFieldResolver 的作用就像一个访问 orm。
如果有人做过类似的事情,欢迎提供任何帮助。我这样做是因为我有大量模型,并且从模型编写直接映射不是一种选择,因为我必须编写超过 10,000 个方法才能让 api 运行。
【问题讨论】:
-
说得更清楚些,你需要贴一些代码或者你得到的意想不到的结果。