2013-12-19 109 views
3

導航屬性我使用的Web API 2 CORS /實體框架6/Breeze.js從亭子單個頁面應用程序和微風查詢並沒有擴張的導航屬性。問題,包括查詢

我會打破它,從服務器到客戶端。

//波蘇斯

public class Foo 
{ 
    public int Id { get; set; } 
    public Bar Bar { get; set; } 
} 

public class Bar 
{ 
    public int Id { get; set; } 
    public string SomeData { get; set; } 
} 

public class FooMap : EntityTypeConfiguration<Foo> 
{ 
    public FooMap() 
    { 
     HasKey(t => t.Id); 

     ToTable("Foo"); 
     Property(t => t.Id).HasColumnName("Id"); 

     HasRequired(t => t.Bar).WithMany().Map(t => t.MapKey("BarId")); 
    } 
} 

//網頁API配置 //省略靜態類和默認路由 //配置是HttpConfiguration

config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 

//微風控制器

[BreezeController] 
public class FooController : ApiController 
{ 
    readonly EFContextProvider<SomeDbContext> _contextProvider = 
     new EFContextProvider<SomeDbContext>(); 

    [HttpGet] 
    public string Metadata() 
    { 
     return _contextProvider.Metadata(); 
    } 

    [HttpGet] 
    public IQueryable<Foo> Foos() 
    { 
     return _contextProvider.Context.Foos; 
    } 
} 

//前端地

// main.js

breeze.NamingConvention.camelCase.setAsDefault(); 

var FooService = (function(breeze) { 
    var service = "http://localhost:58996/breeze/Foos"; 
    breeze.config.initializeAdapaterInstances({ dataService: 'webApi' }); 

    var manager = new breeze.EntityManager(service); 
    var entityQuery = new breeze.EntityQuery(); 

    this.getAll = function(callback, errorCallback) { 
     return manager.executeQuery(entityQuery.from('Foo').take(10).expand('Bar'), callback, errorCallback); 
    }; 
})(window.breeze); 

var fooService = new FooService(); 
fooService.getAll(function(data) { 
    console.log(data); 
}, function(error) { 
    console.log(error); 
}); 

的Fiddler示出了有效載荷JSON:

[ 
    { 
     "$id":"1", 
     "$type":"DataAccess.Models.Foo, DataAccess", 
     "Id":"10", 
     "Bar":{ 
     "$id":"2", 
     "$type":"DataAccess.Models.Bar, DataAccess", 
     "Id":"12", 
     "SomeData":"Hello World" 
     } 
    } 
] 

bar不在鉻陣列中的物體的領域。


編輯:

的解決方案是增加一個屬性來保存BarId並將其設置爲外鍵。

public class Foo 
{ 
    public int Id { get; set; } 
    public int BarId { get; set; } 
    public Bar Bar { get; set; } 
} 

public class FooMap : EntityTypeConfiguration<Foo> 
{ 
    public FooMap() 
    { 
     HasKey(t => t.Id); 

     ToTable("Foo"); 
     Property(t => t.Id).HasColumnName("Id"); 
     Property(t => t.BarId).HasColumnName("BarId"); 

     HasRequired(t => t.Bar).WithMany().HasForeignKey(t => t.BarId); 
    } 
} 

回答

3

什麼我躍起一點是,你沒有一個外鍵(FK)屬性的依賴Foo實體

您已通過您的映射t.MapKey表達識別數據庫中的表(「Foo.BarId」)的FK列。

HasRequired(t => t.Bar).WithMany().Map(t => t.MapKey("BarId")); 

但是你故意不建立在你的Foo實體相應的BarId FK財產。

實體框架可以檢索對象圖缺乏FK性質的關聯。由於您告知實體框架有關FK ,因此它可以在服務器上實現Foo及其Bar。這就是爲什麼你在電線上看到相關的Bar數據。

但BreezeJS缺乏對數據庫的訪問......也不應該有任何數據庫的意識都沒有。微風只知道(通過元數據)你的實體類型屬性。如果沒有FK 財產,微風沒有辦法一個Bar與其父Foo關聯。

BreezeJS可能能夠在緩存中實現Bar實體。我敢打賭(不承諾),你會在那裏找到它,如果你在成功回調突破和執行控制檯以下:

manager.getEntities('Bar'); 

但要BreezeJS,這是在緩存中只是另一個實體。 Breeze無法填充Foo.Bar導航屬性,因爲它不知道FooBar是如何關聯的。 Breeze 需要FK屬性來執行Foo.Bar導航屬性

這是why we say thatBreezeJS協會必須由FK屬性來支持。」

這需要相當的技巧和知識 - 超出了這個答案的範圍 - 與缺少FK性質協會合作。你將不得不用自己的代碼維護導航屬性;微風將無法做到這一點。我的建議(包括我自己):不要去那裏。

所有應該清楚,如果你重新定義「Foo.cs」作爲

public class Foo 
{ 
    public int Id { get; set; } 
    public int BarId { get; set; } // Bar nav's FK 
    public Bar Bar { get; set; } 
} 

順便說一下,萬一有人懷疑,CORS是不是在這個問題的一個因素。

+0

感謝病房!明天我進入辦公室時我會嘗試一下。我有一種感覺,它可能是與外鍵相關的(關於EF中的一對一關係有稀疏的信息),因爲我不知道它是否與我的POCO或我的映射有關。我需要對映射文件進行任何修改,否則插入新的屬性就足夠了? – Romoku

+0

好的,這裏是更新。你說得對,我需要定義單獨的外鍵屬性。我需要在每個屬性的映射文件中更改兩行。 1)添加'Property(t => t.BarId).HasColumnName(「BarId」);'2)改變HasRequired(t => t.Bar).WithMany()。HasForeignKey(t => t.BarId );'。我會將其編輯到我的問題的底部。謝謝您的幫助! – Romoku

+0

很高興工作。現在你可以完全移除'FooMap',因爲你的'Foo'和'Bar'類符合默認的EF約定。當然你真正的應用程序有真正的類,所以可能有其他原因保持EF Fluent API映射類。 – Ward