【问题标题】:Issues including navigation properties in query问题包括查询中的导航属性
【发布时间】:2013-12-20 21:23:51
【问题描述】:

我正在使用来自 bower 的 Web API 2 和 CORS/Entity Framework 6/Breeze.js 用于单页应用程序,并且微风查询没有扩展导航属性。

我将把它从服务器分解到客户端。

// POCO

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);
    }
}

【问题讨论】:

    标签: entity-framework asp.net-web-api cors breeze


    【解决方案1】:

    让我大吃一惊的是,您在依赖 Foo 实体中没有外键 (FK) 属性

    您已通过映射中的t.MapKey 表达式识别了数据库表(“Foo.BarId”)中的 FK 列。

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

    但是您故意没有在您的 Foo 实体中创建相应的 BarId FK 属性。

    Entity Framework 可以检索缺少 FK 属性的关联的对象图。因为您告诉 Entity Framework 关于 FK ,它可以在服务器上实现Foo 及其Bar 。这就是为什么您会在网络上看到相关的Bar 数据。

    但是 BreezeJS 缺乏对数据库的访问……它也不应该有任何数据库意识。 Breeze 只知道(通过元数据)您的实体类型属性。如果没有 FK 属性,Breeze 无法将 Bar 与其父 Foo 关联。

    BreezeJS 可能能够物化缓存中的Bar 实体。我敢打赌(不保证)如果你中断成功回调并在控制台中执行以下命令,你会在那里找到它:

    manager.getEntities('Bar');
    

    但是对于 BreezeJS,这只是缓存中的另一个实体。 Breeze 无法填充Foo.Bar 导航属性,因为它不知道FooBar 是如何相关的。 Breeze需要 FK 属性来实现 Foo.Bar 导航属性

    这是why we say that "BreezeJS 关联必须由 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 不是这个问题的一个因素。

    【讨论】:

    • 谢谢沃德!明天我到办公室时我会试一试。我有一种感觉,它可能与外键相关(关于 EF 中的一对一关系的信息很少),因为我不知道它是否与我的 POCO 或我的映射有关。我需要对映射文件进行任何修改还是插入新属性就足够了?
    • 好的,这是一个更新。你说得对,我需要定义单独的外键属性。我需要在每个属性的映射文件中更改两行。 1) 添加Property(t =&gt; t.BarId).HasColumnName("BarId"); 和 2) 更改HasRequired(t =&gt; t.Bar).WithMany().HasForeignKey(t =&gt; t.BarId);。我将把它编辑到我的问题的底部。感谢您的帮助!
    • 很高兴工作。现在您可以完全删除FooMap,因为您的FooBar 类符合默认的EF 约定。当然,您的真实应用程序具有真实的类,因此保留 EF Fluent API 映射类可能还有其他原因。
    • 我的真实应用程序我首先使用 EF powertools 将数据库逆向工程为代码。数据库架构不如我的示例那么好。
    • 如果您需要将表中的元素与视图中的记录关联起来,您有哪些选择? (不可能在表和视图之间创建foreignKey)@Ward
    猜你喜欢
    • 1970-01-01
    • 2019-12-17
    • 2016-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多