我似乎无法解决我的映射问题;关系是一个用户可能有很多场地,场地必须有一个用户。
我的venue
课程看起来像:
public class Venue : BaseObject, IBaseObject
{
[Required]
public virtual User Owner { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
}
我的User
课程看起来像:
public class User : BaseObject, IBaseObject
{
[Required]
public string Name { get; set; }
[Required]
[DisplayName("Email")]
public string EmailAddress { get; set; }
[Required]
public string Password { get; set; }
public bool Active { get; set; }
public virtual ICollection<Venue> Venues { get; set; }
}
DbContextClass按要求
public class SystemContext : DbContext, IDbContext
{
public SystemContext() :
base("SystemContext")
{
Database.SetInitializer<SystemContext>(null);
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = true;
}
public SystemContext(string connectionstringname = "SystemContext") :
base(connectionstringname)
{
Database.SetInitializer<SystemContext>(null);
Configuration.ProxyCreationEnabled = false;
}
public new IDbSet<T> Set<T>() where T : class
{
return base.Set<T>();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().HasMany(x=>x.Venues);
}
public DbSet<PublicQueries> PublicQueries { get; set; }
public DbSet<Venue> Venues { get; set; }
public DbSet<User> Users { get; set; }
}
当我从数据库加载User
类时Venues
似乎总是为空?
我以前做过类似的事,但不记得我是如何重新安排的。
谢谢
很确定这是一个懒惰的问题。如果您加载具有导航属性(如ICollection<Venues>
)的对象,则默认情况下不会包含它们,因为它们可能有更多导航属性链接到更多对象,这些对象可能具有更多导航属性......在您了解它之前重新加载一半的数据库。当您在访问该导航属性时已经处理了对象出现的上下文时,这是一个特殊问题,因为它没有数据库连接来加载它们,即使它确实意识到它应该这样做。
修复是通过在.Include(u => u.Venues);
中获取DbSet
时告诉实体框架您希望填充该属性。你需要包括System.Data.Entity
来获得Include()
的特殊重载。
你venue
类也应该有一个名为OwnerId
的字段。
您可以将此link作为参考作为延迟加载的开始。
public class Venue : BaseObject, IBaseObject
{
public (int/guid/or other type if you want) OwnerId{get;set;}
[Required]
public virtual User Owner { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
}
然后还要确保你的User
类有一些Id
字段,然后由EF
用作外键
这就是我要做的,
public class Venue : BaseObject, IBaseObject
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id{get;set;}
public int OwnerId{get;set;}
[Required]
public virtual User Owner { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
}
public class User : BaseObject, IBaseObject
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get;set;}
[Required]
public string Name { get; set; }
[Required]
[DisplayName("Email")]
public string EmailAddress { get; set; }
[Required]
public string Password { get; set; }
public bool Active { get; set; }
public virtual ICollection<Venue> Venues { get; set; }
}
public SystemContext() :
base("SystemContext")
{
Database.SetInitializer<SystemContext>(null);
Configuration.ProxyCreationEnabled = true;
Configuration.LazyLoadingEnabled = true;
}
在我的上下文中将“ProxyCreationEnabled”设置为true似乎已经解决了这个问题。
阅读EF 4 - Lazy Loading Without Proxies后引用:
使用具有Entity Framework内置功能的POCO实体时,必须启用代理创建才能使用延迟加载。因此,对于POCO实体,如果ProxyCreationEnabled为false,则即使LazyLoadingEnabled设置为true,也不会发生延迟加载。
检查你的数据库,在Venue表中找到forginKey,看看它是否可以为null。 if可以为null,即0..N,如果不能为null,则为1..N 我想你想要一个1..N
1..N使用flunt api配置,使用代码类似
modelBuilder.Entity<User>().HasMany(x=>x.Venues).WithRequired(x=>x.Owner);
如果您有保存用户标识的属性,则可以使用
modelBuilder.Entity<User>().HasMany(x=>x.Venues).WithRequired(x=>x.Owner).HasForeignKey(x=>x.userid);
或者ef将创建一个db字段
这些配置用户,你也可以配置场地
modelBuilder.Entity<Venues>().HasRequired(x=>x.Owner).WithMany(x=>x.Venues).HasForeignKey(x=>x....)
它做同样的事情
如果你想要一个0..N,你可以将HasRequired / WithRequired更改为HasOptional / WithOptional db字段可以为null
我仍然不确定为什么会发生这种情况(这可能是为了获得更好的性能......)但你必须自己加载属性。
所以在你的情况下,它看起来像这样:
// Load the user from the database
User user = await UserDataContext.Users.SingleOrDefaultAsync(u => u.Id == "UserID");
// Then load in all the venues
await UserDataContext.Entry(user).Collection(u => u.Venues).LoadAsync();
// Now you could access the venues
foreach (var venue in user.Venues) Console.WriteLine(venue);
在一对一映射情况下,只需使用Reference
方法加载属性:
await UserDataContext.Entry(user).Reference(u => u.Venue).LoadAsync();