entity-framework - 问题包括查询中的导航属性

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

我将 Web API 2 与来自 bower 的 CORS/Entity Framework 6/Breeze.js 一起用于单页应用程序,breeze 查询未扩展导航属性。

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

//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 配置 //省略静态类和默认路由 //配置是 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;
    }
}

//前端地

//主.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);
    }
}

最佳答案

令我震惊的是,您在依赖的 Foo 实体中没有外键 (FK) 属性

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

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

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

Entity Framework 可以为缺少 FK 属性的关联检索对象图。因为您将 FK column 告诉了 Entity Framework,所以它可以在服务器上 实现 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 thatBreezeJS 关联必须由 FK 属性支持。

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.

如果您将“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 不是这个问题的一个因素。

关于entity-framework - 问题包括查询中的导航属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20692463/

相关文章:

c# - 如何使用 Entity Framework 6更新相关数据

entity-framework - 使用DbMigrationsConfiguration将SetExecutionStrategy设置为SqlAzureExecutionStrategy?

asp.net - Owin 中间件 vs ExceptionHandler vs HttpMessageHandler (DelegatingHandler)

c# - LINQ to Entities 中的字符串拆分

c# - Entity Framework 5 中的 ExecuteStoreCommand 方法在哪里?

c# - 如何在 MVC4 RC WebApi 中注册自定义模型绑定(bind)器

.net - Angular - 发布到 .NET Framework API 的值始终为 null

github - GitHub Pages上的跨源资源共享

javascript - 为什么这个简单的 CORS 请求要进行飞行前选项检查

Flutter Web 集成测试 CORS XMLHttpRequest 错误