问题包括查询导航属性 [英] Issues including navigation properties in query
问题描述
我使用的Web API 2 CORS /实体框架6 / Breeze.js从亭子单个页面应用程序和微风查询不扩大导航属性。
我要打破它,从服务器到客户端。
//波苏斯
公共类Foo
{
公众诠释标识{搞定;组; }
公共酒吧酒吧{搞定;组; }
}公共类酒吧
{
公众诠释标识{搞定;组; }
公共字符串SomeData {搞定;组; }
}公共类FooMap:EntityTypeConfiguration<富>
{
公共FooMap()
{
HasKey(T => t.Id); ToTable(富);
属性(T => t.Id).HasColumnName(ID); HasRequired(T => t.Bar).WithMany()地图。(T => t.MapKey(BarId));
}
}
//网页API配置
//省略静态类和默认路由
//配置是HttpConfiguration
config.EnableCors(新EnableCorsAttribute(*,*,*));
//微风控制器
[BreezeController]
公共类FooController的:ApiController
{
只读EFContextProvider< SomeDbContext> _contextProvider =
新EFContextProvider< SomeDbContext>(); [HTTPGET]
公共字符串元数据()
{
返回_contextProvider.Metadata();
} [HTTPGET]
公众的IQueryable<富> FOOS()
{
返回_contextProvider.Context.Foos;
}
}
//前端土地
// main.js
breeze.NamingConvention.camelCase.setAsDefault();VAR FooService接口=(函数(清风){
VAR的服务=HTTP://本地主机:58996 /微风/ FOOS
breeze.config.initializeAdapaterInstances({DataService的:'的WebAPI'}); VAR经理=新breeze.EntityManager(服务);
VAR entityQuery =新breeze.EntityQuery(); this.getAll =函数(回调,errorCallback){
返回manager.executeQuery(entityQuery.from('富')取(10).expand('酒吧'),回调,errorCallback);
};
})(window.breeze);VAR FooService接口=新FooService接口();
fooService.getAll(功能(数据){
的console.log(数据);
},功能(错误){
的console.log(错误);
});
提琴手显示了JSON有效载荷:
[
{
$标识:1
$类型:DataAccess.Models.Foo,数据访问
ID:10
酒吧:{
$标识:2
$类型:DataAccess.Models.Bar,数据访问
ID:12,
SomeData:Hello World的
}
}
]
但栏
不在铬数组中的对象的字段。
编辑:
解决方案是增加一个属性来保存 BarId
并将其设置为外键。
公共类Foo
{
公众诠释标识{搞定;组; }
公众诠释BarId {搞定;组; }
公共酒吧酒吧{搞定;组; }
}公共类FooMap:EntityTypeConfiguration<富>
{
公共FooMap()
{
HasKey(T => t.Id); ToTable(富);
属性(T => t.Id).HasColumnName(ID);
属性(T => t.BarId).HasColumnName(BarId); HasRequired(T => t.Bar)。.WithMany()HasForeignKey(T => t.BarId);
}
}
什么我突然跳出来的是你的不必在依赖于外键(FK)财产富
实体。
您已经确定了通过 t.MapKey
前$ P $在映射pssion数据库表(Foo.BarId)的FK列。
HasRequired(T => t.Bar)。.WithMany()地图(T => t.MapKey(BarId));
但你故意不建立在你的富
实体相应的 BarId
FK属性。
实体框架可以检索对象图对缺乏FK的属性关联。因为你告诉实体框架对FK的列,它可以兑现两个富
和酒吧
的服务器的。这就是为什么你看到相关的线酒吧
数据。
但BreezeJS缺乏对数据库的访问......也不应该有任何数据库的意识都没有。微风只知道(通过元数据)的实体类型的属性。如果没有FK的属性,微风已经没有办法关联一个酒吧
与其父富
BreezeJS大概能的物质化的的酒吧
在缓存中的实体。我敢打赌,(没有答应),你会在那里找到它,如果你在成功突破回调和执行控制台以下内容:
manager.getEntities('酒吧');
但要BreezeJS,这是在缓存中只是另一个实体。微风无法填充 Foo.Bar
导航属性,因为它不知道,或如何使用富
和酒吧
有关。微风需要的FK属性来实现 Foo.Bar
导航属性
这是为什么我们说 BreezeJS协会必须由FK特性的支持。的
这需要相当的技巧和知识 - 超越这个答案的范围 - 与缺乏FK性质协会合作。你将不得不保持与自己的code中的导航性能;微风就无法做到这一点。我的建议(包括我自己):不要去那里。
块引用>所有应该很好,如果你重新定义Foo.cs为
公共类Foo
{
公众诠释标识{搞定;组; }
公众诠释BarId {搞定;组; } //酒吧Nav的FK
公共酒吧酒吧{搞定;组; }
}顺便说一下,万一有人怀疑,CORS是不是在这个问题的一个因素。
I am using Web API 2 with CORS/Entity Framework 6/Breeze.js from bower for a single page application and the breeze query is not expanding the navigation property.
I'll break it down from server to client.
// 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 // omitting static class and default route // config is HttpConfiguration
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
// Breeze Controller
[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; } }
// Front end land
// 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 shows the JSON payload:
[ { "$id":"1", "$type":"DataAccess.Models.Foo, DataAccess", "Id":"10", "Bar":{ "$id":"2", "$type":"DataAccess.Models.Bar, DataAccess", "Id":"12", "SomeData":"Hello World" } } ]
but
bar
is not a field of the object in the array in chrome.
Edit:
The solution is to add a property to hold
BarId
and set it as a foreign key.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); } }
解决方案What leaps out at me is that you do not have a Foreign Key (FK) property in the dependent
Foo
entity.You have identified the FK column in the database table ("Foo.BarId") through the
t.MapKey
expression in your mapping.HasRequired(t => t.Bar).WithMany().Map(t => t.MapKey("BarId"));
But you deliberately did not create a corresponding
BarId
FK property in yourFoo
entity.Entity Framework can retrieve object graphs for associations that lack FK properties. Because you told Entity Framework about the FK column, it can materialize both the
Foo
and itsBar
on the server. That's why you see relatedBar
data on the wire.But BreezeJS lacks access to the database ... nor should it have any database awareness at all. Breeze only knows about (through metadata) your entity type properties. Without the FK property, Breeze has no way to associate a
Bar
with its parentFoo
.BreezeJS was probably able to materialize the
Bar
entity in cache. I'll bet (no promise) you'll find it there if you break in the success callback and execute the following in the console:manager.getEntities('Bar');
But to BreezeJS, this is just another entity in cache. Breeze cannot populate the
Foo.Bar
navigation property because it does not know that or how theFoo
and theBar
are related. Breeze needs the FK property to implement thatFoo.Bar
navigation property.This is why we say that "BreezeJS associations must be supported by FK properties."
It takes considerable skill and knowledge - beyond the scope of this answer - to work with associations that lack FK properties. You would have to maintain the navigation properties with your own code; Breeze wouldn't be able to do it. My recommendation (including to myself): don't go there.
All should be well if you redefine "Foo.cs" as
public class Foo { public int Id { get; set; } public int BarId { get; set; } // Bar nav's FK public Bar Bar { get; set; } }
Btw, in case anyone wonders, CORS is not a factor in this question.
这篇关于问题包括查询导航属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!