我毫无疑问会遗漏一些明显的东西,所以也许互联网的集体力量可以向我指出。
我有一个代码第一个数据库结构,包括用户,组和一个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控制器生成的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的答案正确地确定了问题,但是为了便于参考,最简单的解决方法是在breeze控制器中不这样做:
var context = new MyContext();
但是这样做
var context = _myEFContextProvider.Context;
由于EFContextProvider将在其自己的实例上禁用代理创建和延迟加载,并允许您保留虚拟并避免在上下文构造函数中全局禁用延迟加载。
答案 0 :(得分:3)
我认为你可能在EF中使用Lazy Loading。这就是导航属性中有动态代理的原因。
在Breeze文档中说,Lazy Loading不是Breeze的选项:
延迟加载
有几次我们提到了这种可能性 相关实体存在于远程存储中但目前不存在 缓存。 Breeze导航属性仅返回其中的实体 高速缓存中。
在某些系统中,导航属性会自动获取 来自远程存储的相关实体(如果它们尚未存在) 缓存。此过程通常称为“延迟加载”或“延迟加载” 加载“因为相关实体仅在加载到缓存中时 请求。
延迟加载不是Breeze选项。 Breeze希望你加载 相关实体明确。您可以直接加载它们 查询它们或间接作为另一个查询的副产品。
因此,您需要禁用Lazy Load并明确加载Groups
和Type
个实体。
您可以通过在导航属性中删除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");
参考文献: