首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何创建C# odata V4实体关系

如何创建C# odata V4实体关系
EN

Stack Overflow用户
提问于 2017-07-17 19:04:38
回答 3查看 933关注 0票数 0

我使用visual studio 2015和"EF v4 From Database“创建了一个odata数据库项目。

我有两个实体,它们是我从microsoft sql server 2015创建的sql-view,

我可以简单地使用odata uri localhost:post/odata/BookingInfoes('BookingId')或localhsot:post/odata/Timemarkers('BookingId')获取数据。

我的问题是,一个扩展与许多时间标记项相关,我不能使用命令?$ BookingInfo,我在谷歌尝试了很多方法,但仍然没有成功。

我想要像这样的东西

代码语言:javascript
复制
{BookingID:123,BookingDate:"sss",[TimeMarker:[{id:1,info:"sss"},{id:2,info:"balh bla"},{id:3,info:"foo foof oo"}]]}

请帮帮忙,这让我困了一个星期,我不知道该怎么处理。

entiy

代码语言:javascript
复制
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生成的

代码语言:javascript
复制
    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

代码语言:javascript
复制
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

这是TimeMarkersController

代码语言:javascript
复制
  [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

代码语言:javascript
复制
<?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个网址只显示父母的内容,我真的希望他们一起显示。请帮帮忙。

EN

回答 3

Stack Overflow用户

发布于 2017-07-17 22:36:32

我从来没有在sql-view中使用过odata,但我认为您需要在模型中添加一些信息: BookingInfo和TimeMarker之间没有明确的关系。

尝试向视图TimeMaker添加对BookingInfo的显式引用(例如BookingInfoId)和entity TimeMaker:

代码语言:javascript
复制
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的逆属性:

代码语言:javascript
复制
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; }

}

对不起,我不能尝试,但我希望这对你有帮助。

票数 0
EN

Stack Overflow用户

发布于 2017-07-19 18:35:36

我终于把工作做完了

我使用EF designer生成实体,使用图形用户界面创建与Model.Edmx的关系,右键单击您想要创建关系的任何模型,然后选择add association,左侧的"add foreign key properties to the 'entityName‘Entity“

*如果您自动更新模型,所有注释虚拟类都将消失,我不知道为什么,最终我完成了关系

代码语言:javascript
复制
http://localhost:49347/odata/v4/BookingInfoes('key')?$expand=TimeMarkers

供您参考的package.config

代码语言:javascript
复制
<?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>
票数 0
EN

Stack Overflow用户

发布于 2021-04-12 07:35:15

根据你的代码,ODataConventionModelBuilder应该已经正确地定义了你的EdmModel,将来你可以通过检查(并张贴到SO) $metadata响应来确认这一点,你可以通过标准的url看到:

http://localhost:49347/odata/v4/$metadata

背景理论

在OData控制器中,您可以手动准备结构化数据响应,也可以让EnableQueryAttribute为您管理这一切。要获得EnableQueryAttribute的全部好处,您需要从端点方法返回IQueryable<T>响应。

  • 对于返回单个项的端点,您可以使用SingleResult response帮助器函数来返回您希望仅返回单个记录的IQueryable<T>

  • 如果您选择NOT从您的方法返回IQueryable<T>响应,则EnableQueryAttribute仍然可以评估查询选项,但只能根据提供的信息评估它们。

因此,当响应是固定对象或列表,而不是针对数据库的查询时,发生的情况是EnableQueryAttribute针对响应对象创建查询,并且查询选项仅应用于该查询实例。

作为一个通用规则,

.ToList()在你的控制器实现中的查询!

好吧,所以永远不会有一点极端,但要知道,如果您调用的是.ToList(),或者您急于将查询加载到本地变量中,那么EnableQueryAttribute只能处理内存中已经存在的数据。

因此,如果你不想返回一个IQueryable<T>,或者你已经迫不及待地加载了,那么你必须记住包括你想要允许你的客户端$expand的所有导航属性。

实现

您实际上并没有包含您的BookingsController实现,但我确信它与TimeMarkersController的样式相同

因为您的初始GetBookings()GetTimeMarkers()正确地返回了一个IQueryable<T>,并且它们使用[EnableQuery]属性进行了修饰,所以以下带扩展的URL应该可以工作:

所有预订:http://localhost:49347/odata/v4/BookingInfoes?$expand=TimeMarkers

单次预订:http://localhost:49347/odata/v4/BookingInfoes?$expand=TimeMarkers&$filter=BookingID

如果使用上述查询的扩展不起作用,请确保正确定义了EdmModel。

以下两个GetBookingInfo变体都应该正确扩展,第一个版本是最简单的,它只是通过原始数据库查询,在这种情况下没有导航属性将被支持的限制。

代码语言:javascript
复制
// GET: odata/BookingInfoes(123)
[EnableQuery]
public IHttpActionResult GetBookingInfo([FromODataUri] string key)
{
    return SingleResult.Create(db.BookingInfoes.Where(b => b.BookingID == key));
}

或者,如果您想专门限制导航选项,在这种情况下,唯一允许的扩展是在TimeMarkers上,因为它是从数据库读取的唯一数据。您也可能有其他原因急于加载或否则数据记录,我们可以这样做:

代码语言:javascript
复制
// 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;
}

下面的URL将同时适用于这两种情况:

http://localhost:49347/odata/v4/MeetingInfoes('id')?$expand=TimeMarkers

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45142587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档