多对多关系,联结表无法识别

时间:2013-06-30 17:29:00

标签: asp.net asp.net-mvc entity-framework asp.net-mvc-4

我想在ASP.NET MVC4中建立多对多的关系。 目标是使用属于用户的UserProfile对象列表扩展默认的Timeline类。 多个用户可以共享Timeline,因此Timeline类应该包含UserProfile个对象的列表。

时间线课程:

namespace MvcApplication1.Models
{
    public class Timeline
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Color { get; set; }
        public List<UserProfile> Users { get; set; }
    }

    public class TimelineContext : DbContext
    {
        public DbSet<Timeline> Timelines { get; set; }
        public DbSet<UserProfile> UserProfiles { get; set; }

        // Added the following because I saw it on:
        // http://www.codeproject.com/Tips/548945/Generating-Many-to-Many-Relation-in-MVC4-using-Ent
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Timeline>()
                .HasMany(c => c.Users)
                .WithMany(s => s.Timelines)
                .Map(mc =>
                {
                    mc.ToTable("TimelineOwners");
                    mc.MapLeftKey("TimelineId");
                    mc.MapRightKey("UserId");
                });
        }
    }
}

UserProfile类(具有添加属性的默认类):

public class UsersContext : DbContext
{
    public UsersContext()
        : base("DefaultConnection")
    {
    }

    public DbSet<UserProfile> UserProfiles { get; set; }
    public DbSet<Timeline> Timelines { get; set; }

    // Added the following because I saw it on:
    // http://www.codeproject.com/Tips/548945/Generating-Many-to-Many-Relation-in-MVC4-using-Ent
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<UserProfile>()
            .HasMany(c => c.Timelines)
            .WithMany(s => s.Users)
            .Map (mc =>
                {
                   mc.ToTable("TimelineOwners");
                   mc.MapLeftKey("UserId");
                   mc.MapRightKey("TimelineId");
               });
    }
}

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }

    public List<Timeline> Timelines { get; set; }
}

我有一个带外键的连接表:

enter image description here

enter image description here

enter image description here

创建Timeline的实例时,Users列表为null

Timeline timeline = db.Timelines.Find(id); // timeline.Users = null

有人可以赐教,我应该如何设置它?

我是ASP.NET MVC4的新手。

编辑1:我知道我不应该扩展UserProfile,而是创建另一个类来存储用户。一旦多对多关系奏效,我将重构并朝着这个方向前进。 但首先我想知道它为什么不起作用。

编辑2: 双上下文也引起了问题,为两个上下文创建了两个数据库,其中一个纯连接表为空。

2 个答案:

答案 0 :(得分:2)

我建议你完成this article about the options how you can load navigation properties with Entity Framework。这是非常基本的知识,对每种关系都很重要,而不仅仅是多对多的关系。

看那篇文章,你会发现这一行......

Timeline timeline = db.Timelines.Find(id);

...不加载任何相关实体。因此,即使实体在数据库中相关,预期timeline.Usersnull

如果您要加载Users,可以使用预先加载

Timeline timeline = db.Timelines.Include(t => t.Users)
    .SingleOrDefault(t => t.Id == id);

这是一个单一的数据库查询。或者要启用延迟加载,您必须将导航属性标记为virtual

public virtual List<UserProfile> Users { get; set; }

//...

public virtual List<Timeline> Timelines { get; set; }

然后您可以使用原始代码:

Timeline timeline = db.Timelines.Find(id); // first query
var users = timeline.Users;                // second query

这将运行两个单独的查询。第一次访问导航属性时会执行第二次。

BTW:您有两个上下文类 - TimelineContextUsersContext的原因吗? “通常”你只需要一个上下文。

答案 1 :(得分:0)

我不喜欢搞乱内部用户配置文件的工作。我建议创建自己的用户类,将其链接到simplemembershipprovider并在那里添加功能。在最大程度上,您将稍微扩展帐户类以添加更多要注册的字段,但这就是它。

关注this非常方便的指南,让事情有效,如果您遇到错误,请告诉我。