问题包括查询导航属性 [英] Issues including navigation properties in query

查看:164
本文介绍了问题包括查询导航属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的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 your Foo 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 its Bar on the server. That's why you see related Bar 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 parent Foo.

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 the Foo and the Bar are related. Breeze needs the FK property to implement that Foo.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆