【问题标题】:EF 4 Code First and M2M2MEF 4 代码优先和 M2M2M
【发布时间】:2011-03-21 06:42:23
【问题描述】:

使用 Entity Framework 4 并首先编写代码我将如何创建支持此场景的模型:

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

例子:

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

谁能帮我先用代码建模,任何帮助/代码示例,都很棒!

/最好的问候文布拉德

【问题讨论】:

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


    【解决方案1】:

    编辑:这是满足您要求的新模型。

    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:

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

    【讨论】:

    • 谢谢拉迪斯拉夫,但我不确定这是否正确。如果我获取用户,我将能够查看他/她所属的组,但如果我正确阅读此内容,我将无法查看用户对特定组的角色。这将返回为该组添加的所有角色,而不是为属于该组的用户。我希望能够说“给我 Lisa”,然后响应返回 lisa 的用户对象,以及她所属的组。对于每个组,都有一个列表属性,其中包含她在该特定组中拥有的所有角色。
    • 所以这是完全不同的要求。我会考虑的。
    • 对不起,当我写道:“每个用户属于一个或多个组并且对于每个组,用户可以拥有一个或多个角色”时,我认为我在第一个描述中很清楚。希望您现在了解我的要求后可以帮助我。
    • 嗨拉迪斯拉夫!感谢您的好评!像我希望的那样工作。我还有一个问题希望你能回答。有什么方法可以防止对象具有应用程序不需要的属性。例如具有组和用户权限的角色对象。这对应用程序来说是不必要的,并且仅存在以便使用正确的表创建数据库。是否可以在 OnModelCreating 期间通过设置和删除属性来执行此操作?
    • 这是可能的,但您仍然需要至少在关系的一侧有导航属性。您将从 Role 中删除属性并按照第二个映射 sn-p 中所述的类似方式对其进行映射。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 2012-05-17
    相关资源
    最近更新 更多