2014-05-06 115 views
1

我在嘗試展開模型中對象的導航屬性時出現錯誤。Web API空導航屬性

eg. /odata/Products?$expand=ProductDetails 

我收到以下錯誤:

No NavigationLink factory was found for the navigation property 'ProductDetails' from entity type 'ProductModels.Models.Product' on entity set 'Products'. Try calling HasNavigationPropertyLink on the EntitySetConfiguration. 

參數名:navigationProperty

我的模型看起來是這樣的:

public class Person 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 
    [ForeignKey("Name")] 
    public PersonDetails PersonDetails { get; set; } 
} 

public class PersonDetails 
{ 
    [Key] 
    public string FullName { get; set; } 

    public int Age { get; set; } 

} 

它是一個零/一對一的關係你可以看到我的模型有點奇怪,PersonDetails通過Person關聯到Person.Name = PersonDetails .FullName但實體框架6不處理它,並生成如下的SQL:

SELECT 
[Extent1].[Id] AS [Id], 
N'f4243347-5b4c-4790-a07d-e8beb80bea72' AS [C1], 
[Extent1].[Name] AS [Name], 
N'PersonDetails' AS [C2], 
N'f4243347-5b4c-4790-a07d-e8beb80bea72' AS [C3], 
[Extent2].[FullName] AS [FullName], 
[Extent2].[Age] AS [Age], 
CASE WHEN ([Extent1].[Name] IS NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C4] 
FROM [Persons] AS [Extent1] 
LEFT OUTER JOIN [PersonDetails] AS [Extent2] ON [Extent1].[Name] = [Extent2].[FullName] 

而在結果,許多產品詳細記錄是零,這是確定的。

但似乎OData格式化程序有一個問題,其中Person.Name爲空。我有以下我ProductsContext設置:

public System.Data.Entity.DbSet<Product> Products { get; set; 

這ODataConventionModelBuilder:

builder.EntitySet<Vehicle>("Products"); 

我沒有對產品詳細的控制,因爲我不想直接訪問它,只有通過產品控制器。

如果我添加在:

builder.EntitySet<Vehicle>("ProductDetails"); 

然後我得到一個:

The EDM instance of type '[ProductModels.Models.ProductDetails Nullable=True]' is missing the property 'FullName'. 

這是有道理的,因爲全名很可能在該產品詳細記錄空。

我可以看到的唯一方法是使用HasNavigationPropertyLink,而不是像上面那樣構建ProductDetails的標準方式。

任何人都可以給我任何建議我應該做什麼?

回答

-1

試試這個代碼片段:

var products=builder.EntitySet<Vehicle>("Products"); 
    products.HasNavigationPropertiesLink(
       product.NavigationProperties, 
       (entityContext, navigationProperty) => 
       { 
        object id; 
        entityContext.EdmObject.TryGetPropertyValue("ID", out id); 
        return new Uri(entityContext.Url.Link(ODataTestConstants.DefaultRouteName, 
       new 
       { 
        odataPath = entityContext.Url.CreateODataLink(
         new EntitySetPathSegment(entityContext.NavigationSource.Name), 
         new KeyValuePathSegment(id.ToString()), 
         new NavigationPathSegment(navigationProperty)) 
       })); 
       }, true); 
+0

感謝您的答覆。產品似乎沒有NavigationProperties的集合,但product.EntityType的確如此。這是我應該使用的嗎?我可以用任何東西替換ODataTestConstants.DefaultRouteName,還是需要引用某些東西?我可以使用Url.ODataLink而不是Url.CreateODataLink?你能告訴我什麼是entityContext.NavigationSource。名字應該返回 - 是否有另一個我應該參考的庫? – user2363071

+0

添加一些關於代碼如何工作的描述?並回複評論?請.. :) – Rikki

1

ODataConfig.cs加入實體的條目下。

builder.EntitySet<EntityName>(typeof(EntityName).Name); 

,整個代碼會是這樣

public static class ODataConfig 
    { 
     public static void Register(HttpConfiguration config) 
     { 
      ODataModelBuilder builder = new ODataConventionModelBuilder(); 
      builder.EntitySet<EntityName>(typeof(EntityName).Name); 
      var model = builder.GetEdmModel(); 
      config.Routes.MapODataRoute("odata", "odata", model); 

      config.EnableQuerySupport(); 
     } 
    } 
-1

這爲我工作:

foreach (var navProp in products.EntityType.NavigationProperties) 
      { 
products.HasNavigationPropertyLink(
      navprop, 
      (entityContext, navigationProperty) => 
      { 
       object id; 
       entityContext.EdmObject.TryGetPropertyValue("ID", out id); 
       return new Uri(entityContext.Url.CreateODataLink(
        new EntitySetPathSegment(navprop.Name), 
        new KeyValuePathSegment(id.ToString()) 
        )); 
      }, false); 
} 
+0

沒有說明代碼的作用?我嘗試過使用它 - 但沒有EntitySetPathSegment/KeyValuePathSegment類的標誌。哪個版本的OData是這個? – Rikki