我有一个相当大的数据模型,我想使用OData V4协议使用Web API OData公开.
基础数据存储在SQL Server 2012数据库中.该数据库中包含许多DateTime列.
当我接线时,我收到一个错误,即不支持System.DateTime.
所以这是我的问题,我该怎么做才能在OData Feed中看到我的DateTime列?
注意:我无法返回并将所有列更改为DateTimeOffset列.
我尝试更改Entity Framework edmx中列的类型,但它给了我这个错误:
指定的成员映射无效."MyProject.MyEntity"类型中成员'MyPropertyHere'的类型'Edm.DateTimeOffset [Nullable = False,DefaultValue =,Precision =]'与'SqlServer.datetime不兼容[Nullable = False,DefaultValue =,Precision = 3] '成员'MyColumnName''类型'MyDataModel.Store.MyEntity'.
(基本上认为DateTime与DateTimeOffset不兼容.)
Web API OData团队真的只是遗漏了需要使用SQL Server类型的所有人DateTime吗?
更新:我找到了相关的解决方法,但他们需要更新EF模型才能使用它们.如果我能避免,我宁愿不必单独更新几百个属性.
更新:这个问题让我意识到微软管理其OData产品的方式存在很大的缺陷.有很多问题,但这个问题最为明显.Web API OData中存在巨大的缺失功能. 插件的交易和排序是其中两个.这两个项目(在OData规范中并且在Microsoft杀死它之前在WCF数据服务中)对于任何真实系统都是至关重要的.
但是,他们决定花时间去删除对许多开发人员非常有用的功能,而不是将时间放在那些缺少OData规范功能的关键位置.它体现了糟糕的管理,以便在添加急需的功能时优先删除工作功能.
我尝试与Web API OData代表讨论这些问题,最后,我打开了一个问题/票证,几天后关闭了.那是他们愿意做的结束.
正如我所说,Web API OData的管理还有很多问题(与DateTime无关,所以我不会在这里列出). 我一直是OData的坚定支持者,但Web API OData管理层的明显问题迫使我和我的团队/公司放弃了它.
幸运的是,可以设置普通的Web API以使用OData语法.设置控制器的工作量更大,但最终工作得很好.它支持DateTime.(并且似乎管理层至少可以远离制定疯狂的错误决策.)
在odata v4.0中是否有将$ expand和$ select组合在一起的选项?
我有一个场景,我正在尝试获取productItemChoices和item中的特定列.以下查询将为您提供productItemChoices中的所有列.我只需要productItemChoices中的一列
odata/Products(08f80b45-68a9-4a9f-a516-556e69e6bd58)?$expand=productItemChoices($expand=item($select=name))
Run Code Online (Sandbox Code Playgroud) 我有一个ASP.NET 5应用程序,我想用它来使用OData v4.
这是我尝试过的:
1.我导入了以下nuget包:
"Microsoft.AspNet.WebApi": "5.2.3",
"Microsoft.AspNet.OData": "5.7.0",
"Microsoft.AspNet.Hosting": "1.0.0-rc1-final"
Run Code Online (Sandbox Code Playgroud)
2.在Startup.Configure方法中对此进行了调整
GlobalConfiguration.Configure(ConfigOData);
Run Code Online (Sandbox Code Playgroud)
3.最后这是OData配置
private static void ConfigOData(HttpConfiguration config)
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
var EDM = builder.GetEdmModel();
//OData v4.0
config.MapODataServiceRoute("odata", "odata", EDM,
new DefaultODataPathHandler(),
conventions,
new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
}
Run Code Online (Sandbox Code Playgroud)
现在,ODC调用正在由MVC的路由配置处理(很可能是因为我没有正确地向ASP.NET 5注册OData).
请有人帮我这个吗?
我遵循Mike Wasson的这个asp.net教程,设法建立相关实体就好了,但是当我将这个逻辑应用到我的项目时,更复杂的实体关系(其中有更多的实体关系;这是唯一的区别)在OData调用中不会成功,我使用此有效负载得到404:
{
"error": {
"code": "",
"message": "No HTTP resource was found that matches the request URI 'http://localhost:19215/Menus(c94f7f98-6987-e411-8119-984be10349a2)/MenuPermissions'.",
"innererror": {
"message": "No routing convention was found to select an action for the OData path with template '~/entityset/key/unresolved'.",
"type": "",
"stacktrace": ""
}
}
}
Run Code Online (Sandbox Code Playgroud)
该教程没有提到必须设置EdmModel导航,Mike Wasson指出"asp.net是官方文档:-)"; 所以,我花了一些时间试图让这些相关的实体工作,以为我错误地设置了项目.
我认为这可能与NuGet正在安装的ASP.NET OData库版本有关(NuGet Console安装6.9.x,而NuGet Dialog安装6.5.x).我也想知道是不是因为我将项目设置为一个完全空的项目然后使用OWIN,所以我尝试使用纯ASP.NET模板解决方案.我还尝试了其他几种可能的解决方案:我的控制器方法上的OData-route-attributes; 并将我的数据层和模型都包含在同一个库中(我将它们分开以保持DRY); 我甚至试图使用Rick Anderson的WebApi路由调试器 - 我不会再尝试使用它了!
一切都无济于事.
有一段时间他们工作,但我不知道为什么; 他们不再在下一次建造/运行中工作 - 我想我之间改变了一些东西,但它非常小,我在每一步都失去了信心.
然后我决定Mike Wasson必须在他的教程中采取阻力最小的路径,所以我回复到这个问题/答案,并将其修改为与ODataConventionModelBuilder一起使用并重用,我将在下面的答案中解释.
如果有人知道更简单的方法让这个工作,请告诉我,否则我建议只是咬紧牙关并在下面的答案中写下这些EdmModel-Navigations.
我有一个并排的Web API 2.2 APIController和OData v4 ODataController.我的APIController在内部使用路由属性(没有预定义的路由默认值):
[RoutePrefix("api")]
public class MyController : ApiController
{
[HttpGet]
[Route("My")]
public IHttpActionResult Get()
{
//Code Here
}
[HttpGet]
[Route("My")]
public IHttpActionResult Get([FromUri] String mykey)
{
//Code Here
}
}
Run Code Online (Sandbox Code Playgroud)
因此通过./api/My和./api/My/?mykey=value路由到
我已经尝试设置我的ODataController跟随类似的西装:
[ODataRoutePrefix("My")]
public class oMyController : ODataController {
[HttpGet]
public IHttpActionResult Get(ODataQueryOptions<FileModel> queryOptions) {
//Code Here
}
[HttpGet]
[ODataRoute("({mykey})")]
public IHttpActionResult Get([FromODataUri] String mykey) {
//Code Here
}
}
Run Code Online (Sandbox Code Playgroud)
像这样提前定义odata路线:
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<MyModel>("My");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: "odata",
model: builder.GetEdmModel()
);
Run Code Online (Sandbox Code Playgroud)
但尝试访问./odata/My和./odata/My(value)最终进入我的APIController而不是ODataController. …
我在服务器上使用Web Api OData v4,在客户端上使用OData客户端代码生成器.它工作正常,但我不知道如何在客户端上测试代码.
在服务器上,我公开了一个"Levels"dbSet.
这是客户端上的代码段:
public class LevelViewer
{
public virtual ODataContainer Container{get;set;} //t4 template generated
public LevelViewer(ODataContainer container=null)
{
if(container==null)
{
Container=new ODataContainer(new Uri("http://blabla"));
}
}
//I want to test this (actually there are more things, this is an example)
public List<Level> GetRootLevels()
{
return ODataContainer.Levels.Where(l=>l.IsRoot).ToList();
}
}
Run Code Online (Sandbox Code Playgroud)
我接受由T4模板生成的odata容器作为构造函数的参数,以便能够以某种方式模拟它.
单元测试,这是我丢失的地方:
[TestMethod]
public void LevelsVMConstructorTest()
{
List<Level>levels=new List<Level>();
levels.Add(new Level(){Id=1,LevelId=1,Name="abc",IsRoot=True});
IQueryable<Level>levelsIQ=levels.AsQueryable<Level>();
//?
var odataContainerMock=new Mock<ODataContainer>();
odataContainerMock.Setup(m=>m.Levels).Returns( I DON'T KNOW );
//I want to get here …Run Code Online (Sandbox Code Playgroud) 我知道这些扩展用于生成基于Odata服务的客户端代码.
任何人都可以解释利弊吗?
对OData服务的请求类似于下面的请求按预期工作:
http:// localhost:31054/odata/Articles?$ filter = ArticleRatings/any()&$ orderby = ArticleId%20desc&$ expand = Publication&$ format = json
但是,当我将格式更改为xml时,相同的请求将失败,并显示以下错误消息:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace/>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Object of type 'System.Linq.EnumerableQuery`1[System.Web.OData.Query.Expressions.SelectExpandBinder+SelectAllAndExpand`1[DataAccess.OData.Article]]' cannot be converted to type 'System.Collections.Generic.IEnumerable`1[DataAccess.OData.Article]'.
</ExceptionMessage>
<ExceptionType>System.ArgumentException</ExceptionType>
<StackTrace>
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast) at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr) at System.Reflection.MethodBase.CheckArguments(Object[] parameters, …Run Code Online (Sandbox Code Playgroud) 我正在 Dynamics 365 中编写元数据查询,但我认为这个问题对于任何 OData 查询都可能是通用的。
我的问题如下:
在 Dynamics 中,实体中可以有多种类型的字段,例如字符串、布尔值或查找。我想编写一个查询,返回查找正在寻址的实体的类型。
{url}/api/data/v9.0/EntityDefinitions(LogicalName='Account')
?$select=
LogicalName
&$expand=
Attributes(
$select=
LogicalName,
AttributeType,
Targets; -- Problematic property
$filter=
AttributeType+eq+Microsoft.Dynamics.CRM.AttributeTypeCode'Lookup')
Run Code Online (Sandbox Code Playgroud)
如果我在此查询中不包含目标的选择,我会得到正确的结果,即 AttributeType 为 Lookup 的所有属性。
但是当我要求也包含目标时,我收到一条错误消息
Could not find a property named 'Targets' on type 'Microsoft.Dynamics.CRM.AttributeMetadata
Run Code Online (Sandbox Code Playgroud)
由于 Target 属性仅存在于 Lookup 类型的数组中,因此从字符串属性中选择此列将失败并引发此错误。
有没有办法在选择列之前首先过滤查找?我发现这里评估的顺序是
$filter、$inlinecount、$orderby、$skiptoken、$skip、$top、$expand、$select、$format
这正是我所需要的,只是我不认为在 $expand 属性内调用时这个顺序是相同的。
我正在使用 OData Query v4 和 SQL Server 2012 运行一个简单的 .NET Core WebApi 应用程序。
这可行,但速度非常慢:
GET /api-endpoint?$filter=date(MyDateTimeField) ge 2018-01-01&$top=100
Run Code Online (Sandbox Code Playgroud)
由上面的 URL 生成的 SQL 查询:
SELECT TOP 100 * FROM MyTable WHERE ((((DATEPART(year, [MyDateTimeField]) * 10000) + (DATEPART(month, [MyDateTimeField]) * 100)) + DATEPART(day, [MyDateTimeField])) >= (((2018 * 10000) + (1 * 100)) + 1))
Run Code Online (Sandbox Code Playgroud)
当我尝试这样做时:
GET /api-endpoint?$filter=MyDateTimeField ge 2018-01-01T00:00:00.00Z&$top=100
Run Code Online (Sandbox Code Playgroud)
它生成以下 SQL 查询:
SELECT TOP 100 * FROM MyTable WHERE [MyDateTimeField] > '2018-01-01T00:00:00.0000000'
Run Code Online (Sandbox Code Playgroud)
返回此错误:
从字符串转换日期和/或时间时转换失败。
OData 查询语法是什么来生成与此类似的 SQL 查询?
SELECT TOP 100 * …Run Code Online (Sandbox Code Playgroud) odata-v4 ×10
odata ×6
c# ×4
asp.net-core ×2
.net ×1
asp.net ×1
dynamics-crm ×1
expand ×1
moq ×1
query-string ×1
rest ×1
select ×1
unit-testing ×1