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

C# EF 6-一对多映射始终为空,c#,asp.net-mvc,entity-framework,one-to-many,C#,Asp.net Mvc,Entity Framework,One To Many,我似乎无法解决映射问题;关系是一个用户可能有多个场馆,一个场馆必须有一个用户 我的场地课程看起来像: public class Venue : BaseObject, IBaseObject { [Required] public virtual User Owner { get; set; } [Required] [MaxLength(50)] public string Name { get; set; } } public class User

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

我的
场地
课程看起来像:

public class Venue : BaseObject, IBaseObject
{
    [Required]
    public virtual User Owner { get; set; }

    [Required]
    [MaxLength(50)]
    public string Name { get; set; }
}
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; } 
}
我的
User
类看起来像:

public class Venue : BaseObject, IBaseObject
{
    [Required]
    public virtual User Owner { get; set; }

    [Required]
    [MaxLength(50)]
    public string Name { get; set; }
}
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; } 
}
public类用户:BaseObject、IBaseObject
{
[必需]
公共字符串名称{get;set;}
[必需]
[显示名称(“电子邮件”)]
公共字符串电子邮件地址{get;set;}
[必需]
公共字符串密码{get;set;}
公共bool活动{get;set;}
公共虚拟ICollection场馆{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; }
}
公共类SystemContext:DbContext,IDbContext { 公共系统上下文(): 基本(“系统上下文”) { Database.SetInitializer(null); Configuration.ProxyCreationEnabled=false; Configuration.LazyLoadingEnabled=true; } 公共系统上下文(字符串连接stringname=“SystemContext”): 基础(连接字符串名称) { Database.SetInitializer(null); Configuration.ProxyCreationEnabled=false; } public new IDbSet Set(),其中T:class { 返回base.Set(); } 模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder) { 基于模型创建(modelBuilder); modelBuilder.Entity(); } 公共数据库集公共查询{get;set;} 公共数据库集场馆{get;set;} 公共数据库集用户{get;set;} } 当我从数据库加载
用户
类时
场馆
似乎总是为空

我以前也做过类似的事情,但不记得是怎么解决的


谢谢

非常确定这是一个延迟加载问题。如果加载具有导航属性的对象,如
ICollection
,则默认情况下不会包含这些对象,因为它们可能具有更多导航属性,链接到更多对象,而这些对象可能具有更多导航属性。。。在你知道之前,你已经加载了一半的数据库。当您在访问该导航属性时处理了对象产生的上下文时,这是一个特别的问题,因为即使它意识到应该这样做,它也没有数据库连接来加载它们


修复方法是通过添加
.Include(u=>u.visions),告诉实体框架您希望填充该属性当您从
DbSet
获取它们时。您需要包含
System.Data.Entity
以获得
include()

的特定重载,您的
vention
类还应该有一个名为
OwnerId
的字段

您可以将此作为参考,作为延迟加载的开始

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; } 
}
公共课堂场地:BaseObject、IBaseObject
{
[关键]
[数据库生成(DatabaseGeneratedOption.Identity)]
公共int Id{get;set;}
public int OwnerId{get;set;}
[必需]
公共虚拟用户所有者{get;set;}
[必需]
[MaxLength(50)]
公共字符串名称{get;set;}
}
公共类用户:BaseObject、IBaseObject
{
[关键]
[数据库生成(DatabaseGeneratedOption.Identity)]
公共int Id{get;set;}
[必需]
公共字符串名称{get;set;}
[必需]
[显示名称(“电子邮件”)]
公共字符串电子邮件地址{get;set;}
[必需]
公共字符串密码{get;set;}
公共bool活动{get;set;}
公共虚拟ICollection场馆{get;set;}
}

检查您的数据库,在场馆表中找到forginKey,查看它是否可以为空。
如果可以为空,则为0..N;如果不能为空,则为1..N
我想你想要一个1..N

1..N使用flunt api配置,使用如下代码

modelBuilder.Entity<User>().HasMany(x=>x.Venues).WithRequired(x=>x.Owner);
modelBuilder.Entity();
如果您有保存用户ID的属性,则可以使用

modelBuilder.Entity<User>().HasMany(x=>x.Venues).WithRequired(x=>x.Owner).HasForeignKey(x=>x.userid);
modelBuilder.Entity().HasMany(x=>x.victions)。WithRequired(x=>x.Owner)。HasForeignKey(x=>x.userid);
或者ef将创建一个db字段

这些配置用户,您也可以配置场馆

modelBuilder.Entity<Venues>().HasRequired(x=>x.Owner).WithMany(x=>x.Venues).HasForeignKey(x=>x....)
modelBuilder.Entity().HasRequired(x=>x.Owner)。with many(x=>x.vice)。HasForeignKey(x=>x…)
它做同样的事情

如果您想要一个0..N,您可以将HasRequired/WithRequired更改为hasportional/WithOptional
db字段可以为空

public SystemContext():
   public SystemContext() :
        base("SystemContext")
    {
        Database.SetInitializer<SystemContext>(null);
        Configuration.ProxyCreationEnabled = true;
        Configuration.LazyLoadingEnabled = true;
    }
基本(“系统上下文”) { Database.SetInitializer(null); Configuration.ProxyCreationEnabled=true; Configuration.LazyLoadingEnabled=true; }
在我的上下文中将“ProxyCreationEnabled”设置为true似乎解决了这个问题

在阅读了以下引用后:

当使用具有实体框架内置功能的POCO实体时,必须启用代理创建才能使用延迟加载。因此,对于POCO实体,如果ProxyCreationEnabled为false,那么即使LazyLoadingEnabled设置为true,也不会发生延迟加载


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

在你的例子中,它看起来是这样的:

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

您是否尝试过使用
Include
方法?是否可能重复?是否无法自动执行此操作?您确信您的数据库为您指定的用户提供了场地?您是否不正确地播撒测试数据?是的,一个用户和一个场地,它仍然没有显示。这足以使延迟加载发生吗?不,这不是延迟加载问题。如果他将该属性标记为虚拟,它将正确地延迟加载。Include是不必要的。是的,我知道应该这样做,但最近在我的代码中发生了这种情况,事实并非如此