【问题标题】:Breezejs error when loading an entity with related data加载具有相关数据的实体时出现 Breezejs 错误
【发布时间】:2013-09-27 18:18:55
【问题描述】:

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

我有一个代码优先的数据库结构,由用户、组和一个用于链接两者的 GroupUsers 表组成(EF 可以自己处理 n-n 关系,但breathjs 明确需要该表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 控制器生成的 JSON(工作正常)

[
    {
        $id: "1",
        $type: "System.Data.Entity.DynamicProxies.User_41E3B55B982835BEAAA863D9A28B60E1A07D42FBEB52862F05DCD4BAE3F6171C, EntityFrameworkDynamicProxies-MyBreezeTest",
        Groups: [ ],
        Id: "665b2a59-f1ae-41c6-8d6b-df758713db01",
        Name: "Me",
        Email: "me@example.com",
        IsActive: true,
        IsAdmin: true
    }
]

当用户是组的成员时,Breeze API 控制器生成的 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: "me@example.com",
        IsActive: true,
        IsAdmin: true
    }
]

为未来的读者编辑

Margabit 在下面的回答正确识别了问题,但为了便于参考,解决此问题的最简单方法不是在微风控制器中执行此操作:

var context = new MyContext();

而是这样做

var context = _myEFContextProvider.Context;

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

【问题讨论】:

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


    【解决方案1】:

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

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

    延迟加载

    我们曾多次提到这种可能性 相关实体存在于远程存储中但目前不在 缓存。 Breeze 导航属性仅返回位于 缓存。

    在某些系统中,导航属性会自动获取 来自远程存储的相关实体(如果它们尚未在) 缓存。这个过程通常被称为“延迟加载”或“延迟加载” 加载”,因为相关实体仅在 请求。

    延迟加载不是 Breeze 选项。 Breeze 期待您加载 明确的相关实体。您可以直接加载它们 查询它们或间接作为另一个查询的副产品。

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

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

      this.Configuration.LazyLoadingEnabled = false; 
    

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

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

    或者通过在 Query from JavaScript 中加载它们:

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

    参考资料:

    EFContextProvider

    Navigation Properties

    【讨论】:

    • 在阅读了那篇文档后,我尝试通过配置禁用延迟加载,但它仍然不起作用。但是,要么完全禁用代理创建,要么在导航属性上删除虚拟,这很有吸引力。谢谢。
    • 另一个神奇的事情是使用 EFContextProvider.Context 而不是创建一个新的。在早晨寒冷刺眼的光线下,这似乎非常明显。大概是因为 EFContextProvider 正确配置了东西
    猜你喜欢
    • 2021-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-01
    • 2014-02-13
    • 2018-02-12
    • 1970-01-01
    相关资源
    最近更新 更多