EF 6 - 一对多映射始终为空

时间:2014-02-23 15:10:43

标签: c# asp.net-mvc entity-framework one-to-many

我似乎无法解决我的映射问题;关系是一个用户可能有很多场地,场地必须有一个用户。

我的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类时,似乎总是为空?

我之前做过类似的事,但不记得我是如何重新安排的。

由于

5 个答案:

答案 0 :(得分:9)

很确定这是一个懒惰的问题。如果您加载具有导航属性(如ICollection<Venues>)的对象,则默认情况下不会包含它们,因为它们可能有更多导航属性链接到更多对象,这些对象可能具有更多导航属性...并且在您之前知道你加载了一半的数据库。当您在访问该导航属性时已经处理了对象出现的上下文时,这是一个特殊问题,因为它没有数据库连接来加载它们,即使它确实意识到它应该这样做。

修复是告诉实体框架您希望填充{>> 1}}时从.Include(u => u.Venues);获取该属性。您需要包含DbSet才能获得System.Data.Entity的特定重载。

答案 1 :(得分:3)

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; } 
}

答案 2 :(得分:3)

   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,也不会发生延迟加载。

答案 3 :(得分:1)

检查你的数据库,在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);

如果您有保存用户ID的属性,则可以使用

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

答案 4 :(得分:0)

我仍然不确定为什么会发生这种情况(可能是为了获得更好的性能...),但是您必须自己加载该属性。

因此,在您的情况下,它看起来像这样:

// 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();