EF 4 Code First和M2M2M

时间:2011-03-21 06:42:23

标签: many-to-many entity-relationship ef-code-first entity-framework-4.1

首先使用Entity Framework 4和代码如何创建支持此场景的模型:

在应用程序中,有用户,每个用户属于一个更多组,每个用户可以拥有一个更多角色。

示例:

我希望能够说“给我Lisa”,并且响应会返回lisa的用户对象,以及她所属的组。对于每个组,都有一个list属性,其中包含她对该特定组的所有角色

任何人都可以先帮助我使用代码对此进行建模,任何帮助/代码示例都会很棒!

/最好的问候Vinblad

1 个答案:

答案 0 :(得分:2)

编辑:这是符合您要求的新型号。

public class User
{
    public virtual int Id { get; set; }
    public virtual ICollection<UserPermission> Permissions { get; set; }
}

// Permission is extended junction table to model M:N between 
// User and Group but in addition it contains relation to Roles.
// The ony disadvantage is that this model doesn't control that
// role in the collection is also the role related to group. You
// must either enforce it in application logic or create some additional
// database construct to check it.
public class UserPermission
{
    public virtual int UserId {  get; set; }
    public virtual int GroupId { get; set; }

    public virtual Group Group { get; set; }
    public virtual ICollection<Role> Roles { get; set; }
}

public class Group
{
    public virtual int Id { get; set; }
    public virtual ICollection<UserPermission> UserPermissions { get; set; }
    public virtual ICollection<Role> Roles { get; set; }
}


public class Role
{
    public virtual int Id { get; set; }
    public virtual ICollection<Group> Groups { get; set; }
    public virtual ICollection<UserPermission> UserPermissions { get; set; }
}

public class Context : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Group> Groups { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<UserPermission> UserPermissions { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // Permission has composite key
        modelBuilder.Entity<UserPermission>()
            .HasKey(p => new {p.UserId, p.GroupId});

        // Permission doesn't have navigation property to user
        modelBuilder.Entity<User>()
            .HasMany(u => u.Permissions)
            .WithRequired()
            .HasForeignKey(p => p.UserId);

        modelBuilder.Entity<Group>()
            .HasMany(g => g.UserPermissions)
            .WithRequired(p => p.Group)
            .HasForeignKey(p => p.GroupId);
    }
}

如代码所述,存在一些小缺点。您可以通过额外的FK在DB中强制执行数据完整性来避免这种缺点,这些FK无法首先通过代码建模。您可以使用自定义初始值设定项添加该FK:

public class CustomInitializer : DropCreateDatabaseIfModelChanges<Context>
{
    protected override void Seed(Context context)
    {
        context.Database.ExecuteSqlCommand(
            @"ALTER TABLE [dbo].[RoleUserPermissions]  
             WITH CHECK ADD CONSTRAINT [FK_RoleUserPermissions_RoleGroups] 
             FOREIGN KEY([Role_Id], [UserPermission_GroupId])
             REFERENCES [dbo].[RoleGroups] ([Role_Id], [Group_Id])");
    }
}

只需将此添加到您的应用程序初始化(仅用于调试 - 应用程序不应该在发布时删除其数据库):

Database.SetInitializer(new CustomInitializer());