【问题标题】:OData without database but with Foreign Keys没有数据库但有外键的 OData
【发布时间】:2014-02-28 17:41:33
【问题描述】:

我有一个不使用实体框架或任何其他类型数据库的 OData 提供程序。

我使用以下 2 个模型:

public class ItemModel : TrackableBaseModel<Item>
{
    [Key]
    public Int32 ItemId { get; set; }

    public String ItemName { get; set; }

    public virtual ICollection<ItemSerialModel> ItemSerials { get; set; }
}


public class ItemSerialModel : TrackableBaseModel<ItemSerial>
{
    public Int32 ItemSerialId { get; set; }

    [ForeignKey("Item")]
    public Int32? ItemId { get; set; }

    public ItemModel Item {get;set; }
}

但 OData $metadata 显示:

<EntityType Name="ItemModel">
    <Key>
        <PropertyRef Name="ItemId"/>
    </Key>
    <Property Name="ItemId" Type="Edm.Int32" Nullable="false"/>
    <Property Name="ItemName" Type="Edm.String"/>
    <NavigationProperty Name="ItemSerials" Relationship="UserSite.Models.UserSite_Models_ItemModel_ItemSerials_UserSite_Models_ItemSerialModel_ItemSerialsPartner" ToRole="ItemSerials" FromRole="ItemSerialsPartner"/>
</EntityType>
<EntityType Name="ItemSerialModel">
    <Key>
        <PropertyRef Name="ItemSerialId"/>
    </Key>
    <Property Name="ItemSerialId" Type="Edm.Int32" Nullable="false"/>
    <Property Name="ItemId" Type="Edm.Int32"/>
    <NavigationProperty Name="ItemModel" Relationship="UserSite.Models.UserSite_Models_ItemSerialModel_ItemModel_UserSite_Models_ItemModel_ItemModelPartner" ToRole="ItemModel" FromRole="ItemModelPartner"/>
</EntityType>

但这没有多大意义,它带有ItemModelPartner,甚至在项目中都不存在。

如何设置手动 FK,以便导航属性在 OData 中起作用?

WebApiConfig 像这样定义模型:

builder.EntitySet<ItemModel>("Items").EntityType.HasKey(x => x.ItemId);
builder.EntitySet<ItemSerialModel>("ItemSerials").EntityType.HasKey(x => x.ItemSerialId);

【问题讨论】:

  • 除了ItemModel.Item 属性之外还有外键的原因是什么? ItemSerialModel.Item.ItemId 是否有可能不等于 ItemSerialModel.ItemId?如果这两个总是相等的,我认为你根本不需要ItemSerialModel.ItemId。生成的 $metadata 有什么意义? ItemModelPartner 和 ItemSerialsPartner 可能是自动生成的。它们描述了实体集如何通过此导航属性相互映射。除非您有多个具有相同类型的实体集,否则我不会太担心它们。
  • 好吧,问题是当我尝试从中查询时,它会抛出无法找到 ItemPartner 控制器的异常......这很奇怪,因为它甚至不存在。
  • 哦,我明白了。这是使用 ASP.Net Web API 吗?我自己对 Web API 不是很熟悉,所以我不确定模型是如何实际创建的,但我认为将这些信息(和错误消息)添加到您的问题中会有所帮助。
  • 模型是手工创建的 :) 正如我所说,没有底层提供者,但它都是手工完成的。
  • 如果您使用的是WebApi,能否请您发布您的IEdmModel?

标签: c# odata asp.net-web-api


【解决方案1】:

尝试将您的 EdmModel 更改为如下。

ODataConventionModelBuilder v1ODataConventionModelBuilder = new ODataConventionModelBuilder();

v1ODataConventionModelBuilder.EntitySet<ItemModel>("ItemModels");
v1ODataConventionModelBuilder.EntitySet<ItemSerials>("ItemSerials");

config.Routes.MapODataRoute("routename", "routeprefix/", v1ODataConventionModelBuilder.GetEdmModel()

您还应该能够删除以下属性

[ForeignKey("Item")]
public Int32? ItemId { get; set; }

【讨论】:

  • 尝试了您的建议,但没有帮助。如果我删除 ForeinKey 属性,OData 怎么知道关系在哪里?
  • OData 并没有真正使用 ForeignKeys。与其将数据模型视为关系数据库(相关实体通过外键连接),不如将其视为面向对象的数据结构。如果你想创建从类 Bar 到类 Foo 的关系,你只需要在 Bar 上有一个 Foo 类型的属性。
  • 啊,好吧,我知道我不知道。不幸的是,调整后的代码会在我的 $metadata 中出现合作伙伴,这是常见的行为吗?
  • 是的。我建议使用 LinqPad 之类的程序或任何其他 OData 元数据浏览器。这将使您更好地代表您的 edm。
  • 你说得对,我现在注意到 EDM / $metadata 是正确的,但以下步骤:连接到 JayData 无法使用 WebApi OData 正常工作。
【解决方案2】:

对于您的 ItemSerialModel,您应该在最后一行添加“virtual”。就像您在 ItemModel 中所做的一样。

public class ItemSerialModel : TrackableBaseModel<ItemSerial>
{
    public Int32 ItemSerialId { get; set; }

    [ForeignKey("Item")]
    public Int32? ItemId { get; set; }

    public virtual ItemModel Item {get;set; }
 }

至于 Edm Model,你应该按照 Schandlich 的建议去做。希望这会有所帮助。

【讨论】:

  • 添加 virtual 对 OData 有什么作用?
猜你喜欢
  • 1970-01-01
  • 2021-09-06
  • 1970-01-01
  • 1970-01-01
  • 2016-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
相关资源
最近更新 更多