c# - Breezejs 加载具有相关数据的实体时出错

标签 c# javascript entity-framework asp.net-web-api breeze

毫无疑问,我在这里遗漏了一些明显的东西,所以也许互联网的集体力量可以向我指出这一点。

我有一个代码优先的数据库结构,由用户、组和一个链接两者的 GroupUsers 表组成(EF 本身可以处理 n-n 关系,但 Breezejs 明确需要该表 https://stackoverflow.com/a/13636530/249813 )。

然后我尝试在客户端通过 Breezejs 加载用户。当用户不是任何组的成员时,此方法可以正常工作,但当用户显示以下消息时,此方法会失败。

object #<object> has no method getproperty

谁能告诉我哪里出错了?

数据库:

public class MyContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Group> Groups { get; set; }
    public DbSet<GroupUser> GroupUsers { get; set; }
}

public class User
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    public string Name { get; set; }

    [DataType(DataType.EmailAddress)]
    public string Email { get; set; }

    public bool IsActive { get; set; }
    public bool IsAdmin { get; set; }
    public virtual ICollection<GroupUser> Groups { get; set; }
}

public class Group
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    public string Name { get; set; }
    public virtual ICollection<GroupUser> Users { get; set; } 
}

public class GroupUser
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    [ForeignKey("User")]
    public Guid UserId { get; set; }

    [ForeignKey("Group")]
    public Guid GroupId { get; set; }

    public virtual Group Group { get; set; }
    public virtual User User { get; set; }
}

Javascript

var serviceName = '/breeze/admin';
var manager = new breeze.EntityManager(serviceName);
var query = breeze.EntityQuery.from('Users');

manager.executeQuery(query)
    .then(function(data) {
        //do something good
    })
    .fail(function(error) {
        //do something bad.
    });

当用户不是组成员时由 Breeze API Controller 生成的 JSON(工作正常)

[
    {
        $id: "1",
        $type: "System.Data.Entity.DynamicProxies.User_41E3B55B982835BEAAA863D9A28B60E1A07D42FBEB52862F05DCD4BAE3F6171C, EntityFrameworkDynamicProxies-MyBreezeTest",
        Groups: [ ],
        Id: "665b2a59-f1ae-41c6-8d6b-df758713db01",
        Name: "Me",
        Email: "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4e232b0e2b362f233e222b602d2123" rel="noreferrer noopener nofollow">[email protected]</a>",
        IsActive: true,
        IsAdmin: true
    }
]

当用户是组成员时,Breeze API Controller 生成 JSON(失败)

[
    {
        $id: "1",
        $type: "System.Data.Entity.DynamicProxies.User_41E3B55B982835BEAAA863D9A28B60E1A07D42FBEB52862F05DCD4BAE3F6171C, EntityFrameworkDynamicProxies-MyBreezeTest",
        Groups: [
            {
                $id: "2",
                $type: "System.Data.Entity.DynamicProxies.GroupUser_144E644846F6E074946B6DFE31A643AFBBDA0EF263BEBCAA9A6A12E67649A7CF, EntityFrameworkDynamicProxies-MyBreezeTest",
                Group: {
                    $id: "3",
                    $type: "System.Data.Entity.DynamicProxies.Group_4EDDE8FACA0560ADBB390090E3A6A147D06867A4A693B111AECF35D2CE7E458C, EntityFrameworkDynamicProxies-MyBreezeTest",
                    Users: [
                        {
                            $ref: "2"
                        }
                    ],
                    Id: "86365a48-6f45-4614-b0b0-8011ec0e0d77",
                    Name: "Test Group"
                },
                User: {
                    $ref: "1"
                },
                Id: "952faa7b-658d-4e12-8f18-dc9b0898d684",
                UserId: "665b2a59-f1ae-41c6-8d6b-df758713db01",
                GroupId: "86365a48-6f45-4614-b0b0-8011ec0e0d77"
            }
        ],
        Id: "665b2a59-f1ae-41c6-8d6b-df758713db01",
        Name: "Me",
        Email: "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cea3ab8eabb6afa3bea2abe0ada1a3" rel="noreferrer noopener nofollow">[email protected]</a>",
        IsActive: true,
        IsAdmin: true
    }
]

为 future 的读者编辑

下面 Margabit 的答案正确地识别了问题,但是为了便于引用,解决此问题的最简单方法不是在 Breeze Controller 中执行此操作:

var context = new MyContext();

而是这样做

var context = _myEFContextProvider.Context;

因为 EFContextProvider 将在其自己的实例上禁用代理创建和延迟加载,并允许您保持虚拟并避免在上下文构造函数中全局禁用延迟加载。

最佳答案

我认为您可能在 EF 中使用延迟加载。这就是导航属性中具有动态代理的原因。

在 Breeze 文档中说,延迟加载不是 Breeze 的一个选项:

Lazy loading

On several occasions we’ve alluded to the possibility that a related entity exists in remote storage but is not presently in cache. Breeze navigation properties only return entities that are in cache.

In some systems, a navigation property would automatically fetch the related entities from remote storage if they were not already in cache. This process is often called “lazy loading” or “deferred loading” because related entities are only loaded into cache when requested.

Lazy loading is not a Breeze option. Breeze expects you to load related entities explicitly. You can load them either directly by querying for them or indirectly as a byproduct of another query.

因此,您需要禁用延迟加载并显式加载GroupsType 实体。

您可以通过删除导航属性中的virtual(仅删除您不想加载的属性)来删除延迟加载,或者通过在上下文中进行设置来全局删除延迟加载:

  this.Configuration.LazyLoadingEnabled = false; 

您可以通过以下方式包含导航属性:

[HttpGet]
public IQueryable<YourEntity> Orders() {
    return _contextProvider.Context.YourEntities.Include("Groups").Include("Type");
}  

或者通过 JavaScript 将它们加载到查询中:

EntityQuery.from("YourEntities")
.expand("Groups", "Type");

引用文献:

EFContextProvider

Navigation Properties

关于c# - Breezejs 加载具有相关数据的实体时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19032201/

相关文章:

mysql - Visual Studio 2013 - 通过 MySQL 执行 Model.edmx.sql?

c# - 在 C# 和 ASP.NET Core 中单击另一个按钮时如何隐藏按钮并显示它们?

c# - 在 MVC 中按字母顺序排列 SelectList

javascript - 在wordpress中使用ajax更新变量

javascript - 当点击单元格,输入值,但该值与之前的值相同时,Google脚本触发事件

javascript - 使用 javascript 从 json 获取数组

mysql - Visual Studio 报告连接到 MySQL 时超时

asp.net - 使用嵌套对象在 Linq 中将 IQueryable<Entity> 映射到 IQueryable<DTO>

c# - 仅使用 XAML 从 WPF 中的父窗口控制 UserControl 的 Storyboard

c# - 如何使用 Storyboard为 Stackpanel 的边距设置动画?