无需编写代码的OData服务


软件开发最重要的方面之一是快速原型制作。 大多数服务至少需要某些CRUD操作,并且大多数应用程序可以描述为数据驱动的应用程序。 我编写的API基本上从数据库中获取数据,并将其作为JSON返回给客户端。 OdataToEntity是一种从数据库生成API的工具,无需编写单独的REST API。


在本文中,我将展示OdataToEntity如何帮助消除编写CRUD方法的无聊工作。 在上一篇文章中,我讨论了如何以最少的代码创建OData服务,在本文中,我将展示如何在不编写代码的情况下执行此操作。


OdataToEntity.EfCore.DynamicDataContext项目中提供了此功能,该项目是OdataToEntity库的一部分。 HTTP服务器的示例以控制台程序的形式实现,该控制台程序接受到数据库的连接字符串作为输入。 支持的数据库:MySql,PostgreSql,Sql Server。 除了表和CRUD操作外,还可以使用视图,存储过程和功能。


HTTP服务器的描述


服务器源代码在GitHub可用
服务器配置是通过配置文件进行的 。 这是标准的Asp .net核心文件,在其中添加了OdataToEntity键


"OdataToEntity": { "BasePath" : "api", "Provider": "sqlserver", "ConnectionString": "Server=.\\sqlexpress;Initial Catalog=OdataToEntity;Trusted_Connection=Yes;", "UseRelationalNulls": true, "InformationSchemaMappingFileName": "InformationSchemaMapping.json" } 

“ BasePath”是服务器URL中的基本路径。
“提供程序”-数据库类型,可能的值为mysql,postgresql,sqlserver。
“ ConnectionString”是数据库的连接字符串。
“ UseRelationalNulls”-指示是否使用关系数据库的语义
比较零值时。
“ InformationSchemaMappingFileName”-用于在API中显示数据库的附加设置。


该程序自动检测过程,函数,数据库表之间的关系,并检查其外键。 我用它在OData服务模式中嵌入关系。 要进一步自定义名称,请使用InformationSchemaMapping.json文件,该文件是序列化的类InformationSchemaMapping
“操作”键描述存储过程和功能,“表”描述表和视图。 属性“ DbName”-数据库中的名称,“ EdmName”-服务中的名称,“ Exclude”排除数据库和服务对象。 如果存储过程/函数返回一个表,则必须在“ ResultTableDbName”属性中设置表名。 要更改导航属性的名称,需要使用“ Navigations”键,其中“ TargetTableName”属性指向导航属性的目标表,并使用“ NavigationName”(其名称)。 如果该表包含同一表的多个外键,则要区分这些导航属性,而不必使用“ TargetTableName”,而必须指定“ ConstraintName”-数据库外键的名称。 对于多对多属性,您需要指定“ ManyToManyTarget”-目标表的名称(有关多对多实现的更多信息,请参见此链接 )。


代码示例


如果需要在代码中使用此功能,请添加指向OdataToEntity.EfCore.DynamicDataContext项目的链接。


 //Load our schema mappings (optional) InformationSchemaMapping informationSchemaMapping = GetMappings(); //Configure context var optionsBuilder = new DbContextOptionsBuilder<DynamicDbContext>(); optionsBuilder = optionsBuilder.UseSqlServer("Server=.\\sqlexpress;Initial Catalog=OdataToEntity;Trusted_Connection=Yes;"); IEdmModel dynamicEdmModel; //create database schema using (ProviderSpecificSchema providerSchema = new SqlServerSchema(optionsBuilder.Options)) using (var metadataProvider = providerSchema.CreateMetadataProvider(informationSchemaMapping)) { //create ef entity types manager DynamicTypeDefinitionManager typeDefinitionManager = DynamicTypeDefinitionManager.Create(metadataProvider); //Create adapter data access var dataAdapter = new DynamicDataAdapter(typeDefinitionManager); //Build OData edm model dynamicEdmModel = dataAdapter.BuildEdmModel(metadataProvider); } //Create query parser var parser = new OeParser(new Uri("http://dummy"), dynamicEdmModel); //Query var uri = new Uri("http://dummy/Orders?$expand=Customer,Items&$orderby=Id"); //The result of the query var stream = new MemoryStream(); //Execute query await parser.ExecuteGetAsync(uri, OeRequestHeaders.JsonDefault, stream, CancellationToken.None); stream.Position = 0; //Get result as string Console.WriteLine(new StreamReader(stream).ReadToEnd()); 

如何运作


information_schema视图可建立实体框架上下文。 上下文的实体是抽象类DynamicType的后代。 此类对表中的列总数施加了限制,不应超过50。对于来自主键50和外键30的属性,导航属性的数量不应超过。


表和视图的总数限制为110,此数目受DynamicType类实现的限制。 您可以通过将属性或类添加到源代码中来增加它们的数量。
OData模式是在实体框架上下文的基础上构建的,正如我之前的文章中已经描述的那样。 此方案对于将请求转换为表达式树是必需的,该树将传递给EntityFramework上下文。


源代码结构


解决-sln \ OdataToEntity.Test.DynamicDataContext.sln
项目- 源\ OdataToEntity.EfCore.DynamicDataContext
HTTP服务器-test \ OdataToEntity.Test.DynamicDataContext.AspServer
测试-OdataToEntity.Test.DynamicDataContext
SQL测试基础脚本- 测试\ sql_scripts

Source: https://habr.com/ru/post/zh-CN459656/


All Articles