我使用Visual Studio 2015和#34; EF Designer From Database"
创建了一个odata v4项目我有2个实体,他们是我从microsoft sql server 2015创建的sql-view,
我可以用简单的odata uri获取数据 localhost:post / odata / BookingInfoes(' BookingId')或 localhsot:post / odata / Timemarkers(' BookingId')
我的问题是一个BookingInfo涉及许多时间标记项目和 我无法使用命令?$ expand,我在谷歌尝试了很多方法,但仍然没有运气,
我想要像
这样的东西{BookingID:123,BookingDate:"sss",[TimeMarker:[{id:1,info:"sss"},{id:2,info:"balh bla"},{id:3,info:"foo foof oo"}]]}
请帮助,这让我困扰了一个星期,我不知道该怎么处理。
entiy BookingInfo
namespace wcod.Models
{
using System;
using System.Collections.Generic;
public partial class BookingInfo
{
public BookingInfo()
{
var TimeMarkerList = new List<TimeMarker>();
}
public string BookingID { get; set; }
public string BookingDate { get; set; }
public string BookName { get; set; }
public string ChiBookName { get; set; }
public string VideoSource_1500 { get; set; }
public string VideoSource_300 { get; set; }
public string VideoSource_Archive { get; set; }
public string MobileVideoSource { get; set; }
public string languages { get; set; }
public string SeekTime { get; set; }
public Nullable<int> IsVideo { get; set; }
public string AvailableLangs { get; set; }
public Nullable<int> StatusMarkers { get; set; }
public string BookRoomID { get; set; }
public Nullable<System.DateTime> StartTime { get; set; }
public Nullable<int> nexturl { get; set; }
public string StrBookingStartTime { get; set; }
public string BookomgStatus { get; set; }
public virtual ICollection<TimeMarker> TimeMarkers { get; set; }
}
}
TimeMarker也是从sql-view
生成的 namespace wcod.Models
{
using System;
using System.Collections.Generic;
public partial class TimeMarker
{
public Nullable<long> nrow { get; set; }
public Nullable<System.DateTime> StartTime { get; set; }
public Nullable<int> OrderNo { get; set; }
public string MeetingID { get; set; }
public string AgendaName { get; set; }
public string ChiAgendaName { get; set; }
public int AgendaCode { get; set; }
public string AgendaTime { get; set; }
public string SpeakerCode { get; set; }
public Nullable<int> MarkerID { get; set; }
public string AgendaRunningTime { get; set; }
public Nullable<bool> AllLangFail { get; set; }
public Nullable<bool> isLive { get; set; }
public string PopUpMsg { get; set; }
public Nullable<bool> HasVideo { get; set; }
public string TimeMarkerId { get; set; }
public virtual BookingInfo BookingInfo { get; set; }
}
}
WebApiConfig
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Web.Http;
using System.Web.Http.OData.Builder;
using System.Web.Http.OData.Extensions;
using System.Web.OData.Extensions;
using wcod3.Models;
namespace wcod3
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
ODataModelBuilder builder = new ODataConventionModelBuilder();
config.Count().Filter().OrderBy().Expand().Select().MaxTop(null);
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.Indented;
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// var json = config.Formatters.JsonFormatter;
builder.EntitySet<TimeMarker>("TimeMarkers");
builder.EntitySet<MeetingInfo>("BookingInfoes");
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapODataServiceRoute("odata", "odata/v4", builder.GetEdmModel());
}
}
}
这是我的BookingsController
heres是TimeMarkersController
[EnableQuery]
public IQueryable<TimeMarker> GetTimeMarkers()
{
return db.TimeMarkers;
}
// GET: odata/TimeMarkers(5)
[EnableQuery]
public List<TimeMarker> GetTimeMarker([FromODataUri] string key)
{
// return SingleResult.Create(db.TimeMarkers.Where(timeMarker => timeMarker.MeetingID == key));
// return List
return db.TimeMarkers.Where(timeMarker => timeMarker.MeetingID == key).ToList() ;
}
public List<MeetingInfo> GetMeetingInfo([FromODataUri] string key)
{
return db.MeetingInfoes.Where(mi => mi.MeetingID == key).ToList();
}
和packages.config
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.1.3" targetFramework="net452" />
<package id="Microsoft.AspNet.OData" version="6.0.0" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.0" targetFramework="net452" />
<package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net452" />
<package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net452" />
<package id="Microsoft.Extensions.DependencyInjection" version="1.0.0" targetFramework="net452" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.0.0" targetFramework="net452" />
<package id="Microsoft.Net.Compilers" version="1.0.0" targetFramework="net452" developmentDependency="true" />
<package id="Microsoft.OData.Core" version="7.0.0" targetFramework="net452" />
<package id="Microsoft.OData.Edm" version="7.0.0" targetFramework="net452" />
<package id="Microsoft.Spatial" version="7.0.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net452" />
<package id="System.Spatial" version="5.6.0" targetFramework="net452" />
</packages>
http://localhost:49347/odata/v4/TimeMarkers('id')/?$expand=BookingInfo
http://localhost:49347/odata/v4/TimeMarkers('id')?$expand=BookingInfo
http://localhost:49347/odata/v4/MeetingInfoes('id')/?$expand=TimeMarkers
http://localhost:49347/odata/v4/MeetingInfoes('id')?$expand=TimeMarkers
以上所有4个url仅显示父内容,我真的希望它们一起显示。 请帮忙。
答案 0 :(得分:0)
我从不使用带有sql-view的odata,但我认为你需要为你的模型添加一些信息:BookingInfo和TimeMarker之间没有明确的关系。
尝试向View TimeMaker添加对BookingInfo(例如BookingInfoId)以及实体TimeMaker的显式引用:
public partial class TimeMarker
{
public Nullable<long> nrow { get; set; }
public Nullable<System.DateTime> StartTime { get; set; }
public Nullable<int> OrderNo { get; set; }
public string MeetingID { get; set; }
public string AgendaName { get; set; }
public string ChiAgendaName { get; set; }
public int AgendaCode { get; set; }
public string AgendaTime { get; set; }
public string SpeakerCode { get; set; }
public Nullable<int> MarkerID { get; set; }
public string AgendaRunningTime { get; set; }
public Nullable<bool> AllLangFail { get; set; }
public Nullable<bool> isLive { get; set; }
public string PopUpMsg { get; set; }
public Nullable<bool> HasVideo { get; set; }
public int BookingInfoId { get; set; }
[ForeignKey("BookingInfoId ")]
public virtual BookingInfo BookingInfo { get; set; }
}
然后将BookingInfo设置为TimeMarkers的反向属性:
public partial class BookingInfo
{
[Required]
public string BookingID { get; set; }
public string BookingDate { get; set; }
public string MeetName { get; set; }
public string ChiMeetName { get; set; }
public string VideoSource_1500 { get; set; }
public string languages { get; set; }
public string AvailableLangs { get; set; }
public Nullable<int> StatusMarkers { get; set; }
public string MeetRoomID { get; set; }
public Nullable<System.DateTime> StartTime { get; set; }
public Nullable<int> nexturl { get; set; }
public string StrBookingStartTime { get; set; }
public string MeetomgStatus { get; set; }
[InverseProperty("BookingInfo")]
public virtual ICollection<TimeMarker> TimeMarkers { get; set; }
}
抱歉,我不能尝试,但我希望这能帮到你。
答案 1 :(得分:0)
我终于完成了工作,
我使用EF设计器生成实体 使用GUI创建与Model.Edmx的关系并右键单击 您要创建关系的任何模型,然后选择添加关联 离开&#34;将外键属性添加到&#39; entityName&#39;实体&#34;
*如果您自动更新模型,所有注释虚拟课程将消失,我不知道为什么,最后我完成了关系
http://localhost:49347/odata/v4/BookingInfoes('key')?$expand=TimeMarkers
package.config供您参考
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.1.3" targetFramework="net452" />
<package id="Microsoft.AspNet.OData" version="6.0.0" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.OData" version="5.3.1" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.0" targetFramework="net452" />
<package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net452" />
<package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net452" />
<package id="Microsoft.Extensions.DependencyInjection" version="1.0.0" targetFramework="net452" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.0.0" targetFramework="net452" />
<package id="Microsoft.Net.Compilers" version="1.0.0" targetFramework="net452" developmentDependency="true" />
<package id="Microsoft.OData.Core" version="7.0.0" targetFramework="net452" />
<package id="Microsoft.OData.Edm" version="7.0.0" targetFramework="net452" />
<package id="Microsoft.Spatial" version="7.0.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net452" />
<package id="System.Spatial" version="5.6.0" targetFramework="net452" />
</packages>
答案 2 :(得分:0)
根据您的代码,ODataConventionModelBuilder
应该正确定义了您的 EdmModel,将来您可以通过检查(并发布到 SO)$metadata 响应来确认这一点,您可以通过标准网址查看:< /p>
http://localhost:49347/odata/v4/$metadata
在 OData 控制器中,您可以手动准备结构化数据响应,也可以让 EnableQueryAttribute
为您管理这一切。要从 EnableQueryAttribute
获得全部好处,您需要从端点方法返回 IQueryable<T>
响应。
对于返回单个项目的端点,您可以使用 SingleResult
响应辅助函数返回一个您希望只返回一条记录的 IQueryable<T>
。
如果您选择 NOT 从您的方法返回 IQueryable<T>
响应,那么 EnableQueryAttribute
仍然可以评估查询选项,但它只能评估它们已提供的信息。
因此,当响应是固定对象或列表而不是对数据库的查询时,EnableQueryAttribute
会针对响应对象创建查询,并且查询选项仅应用于该查询实例.
作为一般规则,从不 .ToList()
控制器实现中的查询!
好的,所以从不有点极端,但是要知道,如果您正在调用 .ToList()
或者您已经急切地将查询加载到局部变量中,那么 {{1} } 只能处理内存中已经存在的数据。
因此,如果您不想要返回一个 EnableQueryAttribute
或者您急切地加载,那么您必须记住包括所有您的导航属性希望允许您的客户IQueryable<T>
。
您实际上并未包含您的 $expand
实现,但我确定它与 BookingsController
的风格相同
因为您的初始 TimeMarkersController
和 GetBookings()
正确返回了 GetTimeMarkers()
,并且它们带有 IQueryable<T>
属性,以下带有扩展的 URL 应该可以使用:>
所有预订:
[EnableQuery]
单次预订:
http://localhost:49347/odata/v4/BookingInfoes?$expand=TimeMarkers
如果使用上述查询的扩展不起作用,请确保您的 EdmModel 定义正确。
http://localhost:49347/odata/v4/BookingInfoes?$expand=TimeMarkers&$filter=BookingID
的以下两个变体都应该正确展开,第一个版本最简单,它只是通过原始数据库查询,在这种情况下对支持哪些导航属性没有限制。< /p>
GetBookingInfo
或者,如果您想特别限制导航选项,在这种情况下,允许的 ONLY 扩展位于 // GET: odata/BookingInfoes(123)
[EnableQuery]
public IHttpActionResult GetBookingInfo([FromODataUri] string key)
{
return SingleResult.Create(db.BookingInfoes.Where(b => b.BookingID == key));
}
上,因为它是从数据库。您可能还有其他原因急切加载或以其他方式加载数据记录,我们可以这样做:
TimeMarkers
以下网址适用于这两种情况:
// GET: odata/BookingInfoes(123)
[EnableQuery]
public BookingInfo GetBookingInfo([FromODataUri] string key)
{
var booking = db.BookingInfoes.Include(b => b.TimeMarkers)
.Where(b => b.BookingID == key)
.Single();
// TODO: other processing...
return booking;
}