我们想创建一个OData REST API。我们的数据模型是每个客户都有自己的数据库。所有数据库对象在所有客户数据库中具有相同的定义,但单个表除外。
我们将致电客户特定的联系人表。当客户添加列时,系统会创建一个标准化名称的列,其中的定义是由用户在UI中选择的选项翻译而来的。用户仅通过他们指定的字段名称引用列数据,以使用户能够生成友好查询。
在我看来,可以使用以下方法为所描述的模型启用OData:
1)创建OData打开类型以满足动态属性。这具有以下缺点:用户请求客户不提供可以查询的动态属性的指示。即使它们将为用户所知(通过令牌认证)。此外,由于动态属性是字典,因此需要一些数据透视和低效的查询编写。不确定如何为动态属性实现IQueryable处理查询选项以启用我们自己的自定义字段查询。
2)用例如POCO创建一个POCO类50个房产; CustomField1,CustomField2 ...然后以某种方式控制暴露哪些字段以用于OData调用。然后,我们将包含一个单独的API调用来公开自定义字段映射。例如。自定义字段友好名称MobileNumber = CustomField12。
3)在运行时,检查自上次检查后表的列定义是否已更改。如果有,使用CodeDom生成特定于客户的类并将其注册到OData。旨在为每个客户提供唯一的URL。例如。 http://domain.name/ {customer guid} / odata
我认为我们的理想选择是选项2.但是,CustomField1可能是nvarchar,int,decimal,datetime等基础SQL数据类型的事实,会增加复杂性。
有没有人有一个如何实现所描述的令人满意的工作实例?
提前感谢您的帮助。 瑞克
答案 0 :(得分:0)
我们遇到了类似的情况,但我们的整个数据集在运行时都是未知的。使用ODataConventionModelBuilder
和EdmModel
类,可以在运行时动态地向模型添加属性。
我不确定您是否必须手动添加此对象类型的所有属性,即使其中只有一些是未知的,或者您是否可以添加主对象然后添加动态对象,但我猜要么是可行的。
如果您可以掌握它在服务器上的哪种类型的用户,则可以只添加您感兴趣的属性(例如选项3,但不需要CodeDom)。
此处的OData示例中有一个这种无类型OData服务器的示例,可以帮助您入门:https://github.com/OData/ODataSamples/tree/master/WebApi/v4/ODataUntypedSample
答案 1 :(得分:0)
我们进行的研究实际上将选项1作为某些操作的最合适方法。即,创建一个SQL视图,将表中的数据显示为表中每列的列/值列的键/值对。这适用于返回小数据集的查询。这比选项3少得多,并且对用户的混淆比选项2少。不可见的查询将字段值转换为nvarchar(字符串)值,因此意味着按列值数据类型在UI中进行过滤并不容易实现。 (如果我们决定实现这种能力,我相信这可以通过创建一个派生自EnablQueryAttribute的自定义属性,用它标记控制器动作并在执行之前操纵IQueryable来实现。)
但是,我们希望公开一个/ Contacts / Export端点,当调用它时,将从具有固定架构的表中输出列,这些架构连接在具有客户机特定架构的表上并输出到CSV文件。一直使用OData支持的过滤器语法。我们的一个客户数据库拥有超过1,200万行数据,由大约30列组成。
为了达到这个目的,看起来我们最好的选择是使用Microsoft.OData.Core.UriParser.UriQueryExpressionParser类,不幸的是,微软在他们的智慧中宣称这是内部的,以及其中的许多内容。的家属。
走一个从OData支持的查询选项构建的抽象语法树,并将我们自己的访问者应用于每个节点以构建一些动态Linq查询/ SQL似乎是一种可能的解决方案。
暂时我们将简单地实施一组受支持的$ filter标准,而不支持对括号进行分组。