我正在使用Web API 2与来自bower的CORS / Entity Framework 6 / Breeze.js进行单页面应用程序,而breeze查询不会扩展导航属性。
我会将其从服务器分解为客户端。
// POCOs
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"));
}
}
// Web API配置 //省略静态类和默认路由 // config是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
不是chrome中数组中对象的字段。
编辑:
解决方案是添加一个属性来保存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);
}
}
答案 0 :(得分:3)
对我来说,是什么?你在依赖Foo
实体中没有外键(FK)属性。
您已通过映射中的t.MapKey
表达式在数据库表(“Foo.BarId”)中标识了FK列。
HasRequired(t => t.Bar).WithMany().Map(t => t.MapKey("BarId"));
但您故意未在BarId
实体中创建相应的Foo
FK属性。
实体框架可以检索缺少FK属性的关联的对象图。因为您告诉Entity Framework有关FK 列的信息,所以它可以实现服务器上的Foo
及其Bar
。这就是您在线上看到相关Bar
数据的原因。
但是BreezeJS无法访问数据库......也不应该有任何数据库意识。 Breeze只知道(通过元数据)您的实体类型属性。如果没有FK 属性,则Breeze无法将Bar
与其父Foo
相关联。
BreezeJS可能实现缓存中的Bar
实体。如果你打破成功回调并在控制台中执行以下操作,我会打赌(没有承诺)你会在那里找到它:
manager.getEntities('Bar');
但是对于BreezeJS来说,这只是缓存中的另一个实体。 Breeze无法填充Foo.Bar
导航属性,因为它不知道Foo
和Bar
是否相关。 Breeze 需要FK属性来实现Foo.Bar
导航属性。
这是why we say that“ FK属性必须支持BreezeJS关联。 ”
与缺乏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不是这个问题的一个因素。