简体   繁体   English

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

[英]EF 6 - One To Many Mapping Always Null

I can't seem to resolve my mapping issue; 我似乎无法解决我的映射问题; The relationship is one user may have many venues, A venue must have a user. 关系是一个用户可能有很多场地,场地必须有一个用户。

My venue class looks like: 我的venue类看起来像:

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

    [Required]
    [MaxLength(50)]
    public string Name { get; set; }
}

My User class looks like: 我的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 as requested 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; }
}

When I load the User class from the database Venues always seems to be null? 当我从数据库加载User类时, Venues似乎总是为空?

I've done something similar before but can't remember how I resoled this. 我以前做过类似的事,但不记得我是如何重新安排的。

Thanks 谢谢

Pretty sure this is a lazy-load issue. 很确定这是一个懒惰的问题。 If you load an object with navigation properties such as your ICollection<Venues> then they won't be included by default, because they might have more navigation properties linking to more objects, which may have more navigation properties... and before you know it you're loading half the database. 如果加载具有导航属性的对象,例如ICollection<Venues>则默认情况下不会包含它们,因为它们可能有更多导航属性链接到更多对象,这些对象可能具有更多导航属性...并且在您知道之前你加载了一半的数据库。 This is a particular problem when you've disposed of the context the object came out of by the time you go to access that navigation property, because then it doesn't have a database connection to load them from even if it did realise that it should be doing so. 当您在访问该导航属性时已经处理了对象出现的上下文时,这是一个特殊问题,因为它没有数据库连接来加载它们,即使它确实意识到它应该这样做。

The fix is to tell Entity Framework that you want that property to be populated, by adding .Include(u => u.Venues); 解决方法是通过添加.Include(u => u.Venues);告诉实体框架您希望填充该属性.Include(u => u.Venues); when you get them from the DbSet . 当你从DbSet获取它们时。 You'll need to include System.Data.Entity to get that particular overload of Include() . 您需要包含System.Data.Entity以获取Include()特定重载。

You venue class should also have a field called OwnerId . 您的venue类还应该有一个名为OwnerId的字段。

You can take this link as reference as a start for lazy loading. 您可以将此链接作为参考作为延迟加载的开始。

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

then also make sure your User class has some Id field which will then be used as foreign Key by EF 然后还要确保您的User类有一些Id字段,然后由EF用作外键

This is what I would do, 这就是我要做的,

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

Setting "ProxyCreationEnabled" to true within my context seemes to have solved this issue. 在我的上下文中将“ProxyCreationEnabled”设置为true似乎已经解决了这个问题。

After reading EF 4 - Lazy Loading Without Proxies which quotes: 阅读EF 4 - Lazy Loading Without Proxies后引用:

When using POCO entities with the built-in features of Entity Framework, proxy creation must be enabled in order to use lazy loading. 使用具有Entity Framework内置功能的POCO实体时,必须启用代理创建才能使用延迟加载。 So, with POCO entities, if ProxyCreationEnabled is false, then lazy loading won't happen even if LazyLoadingEnabled is set to true. 因此,对于POCO实体,如果ProxyCreationEnabled为false,则即使LazyLoadingEnabled设置为true,也不会发生延迟加载。

check you database,find the forginKey in Venue table,see is it can be null. 检查你的数据库,在Venue表中找到forginKey,看看它是否可以为null。
if can be null,that is 0..N,if can not be null,that is 1..N if可以为null,即0..N,如果不能为null,则为1..N
i think you want a 1..N 我想你想要一个1..N

1..N config with flunt api,use code like 1..N使用flunt api配置,使用代码类似

modelBuilder.Entity<User>().HasMany(x=>x.Venues).WithRequired(x=>x.Owner);

if you has a property to save the userid,you can use 如果您有保存用户标识的属性,则可以使用

modelBuilder.Entity<User>().HasMany(x=>x.Venues).WithRequired(x=>x.Owner).HasForeignKey(x=>x.userid);

or ef will create a db field 或者ef将创建一个db字段

these config User,and you can config Venues too 这些配置用户,你也可以配置场地

modelBuilder.Entity<Venues>().HasRequired(x=>x.Owner).WithMany(x=>x.Venues).HasForeignKey(x=>x....)

it do same thing 它做同样的事情

and if you want a 0..N,you can change the HasRequired/WithRequired to HasOptional/WithOptional 如果你想要一个0..N,你可以将HasRequired / WithRequired更改为HasOptional / WithOptional
the db field can be null db字段可以为null

I'm still not sure why this happens (it's probably for better performance...) but you would have to load the property yourself. 我仍然不确定为什么会发生这种情况(这可能是为了获得更好的性能......)但你必须自己加载属性。

So in your case, it would look like this: 所以在你的情况下,它看起来像这样:

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

In a one to one mapping situation, simply load the property using the Reference method: 在一对一映射情况下,只需使用Reference方法加载属性:

await UserDataContext.Entry(user).Reference(u => u.Venue).LoadAsync();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM