代码之家  ›  专栏  ›  技术社区  ›  DavidGouge

实体框架代码优先树模型

  •  2
  • DavidGouge  · 技术社区  · 13 年前

    我有以下实体:

    public class Module
    {
        public Module()
        {
            SubModules = new List<Module>();
        }
    
        public int Id { get; set; }
        public string Title { get; set; }
        public string Action { get; set; }
        public string Controller { get; set; }
        public string Icon { get; set; }
    
        public List<Module> SubModules { get; set; }
    }
    

    当通过Code First进行初始化时,它会生成下表Schema:

    CREATE TABLE [dbo].[Modules](
        [Id] [int] IDENTITY(1,1) NOT NULL,
        [Title] [nvarchar](max) NULL,
        [Action] [nvarchar](max) NULL,
        [Controller] [nvarchar](max) NULL,
        [Icon] [nvarchar](max) NULL,
        [Module_Id] [int] NULL,
     CONSTRAINT [PK_dbo.Modules] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC
    )WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF)
    )
    
    GO
    ALTER TABLE [dbo].[Modules]  WITH CHECK ADD  CONSTRAINT [FK_dbo.Modules_dbo.Modules_Module_Id] FOREIGN KEY([Module_Id])
    REFERENCES [dbo].[Modules] ([Id])
    GO
    ALTER TABLE [dbo].[Modules] CHECK CONSTRAINT [FK_dbo.Modules_dbo.Modules_Module_Id]
    GO
    

    问题是,当我用一个父模块(module_Id为null)和两个子模块(父模块的module_Id)填充这个表并查询DBContext的modules集合时,我会正确地得到父模块及其子模块集合,但也会得到它们自己返回的子模块。

    因此,DbContext中的Modules集合看起来有点像这样:

    ParentModule
    ---Child Module
    ---Child Module
    Child Module
    Child Module
    

    我需要的是,这两个子模块本身不能作为模块返回,而只能作为父模块的子模块返回。

    希望我已经解释好了。

    2 回复  |  直到 13 年前
        1
  •  5
  •   Kristof Claes    11 年前

    我将添加ParentModuleId属性( int? )到您的模块类。

    public class Module
    {
        public Module()
        {
            SubModules = new List<Module>();
        }
    
        public int Id { get; set; }
        public string Title { get; set; }
        public string Action { get; set; }
        public string Controller { get; set; }
        public string Icon { get; set; }
    
        public int? ParentModuleId { get; set; }
    
        [ForeignKey("ParentModuleId")]
        public virtual ICollection<Module> SubModules { get; set; }
    }
    

    注意,我还添加了 ForeignKey 属性,以确保新的ParentModuleId属性用作外键列。

    通过这种方式,您可以手动检查父模块的存在。

    然后,您可以获得这样的“根模块”:

    var rootModules = context.Modules.Where(x => x.ParentModuleId == null);
    

    如果你非常需要,你也可以创建一个扩展方法:

    public IQueryable<Module> WithoutParent(this IQueryable<Module> modules)
    {
        return modules.Where(x => x.ParentModuleId == null);
    }
    
    var rootModules = context.Modules.WithoutParent();
    
        2
  •  2
  •   jvdveuten    12 年前

    无法添加评论,但克里斯托夫·克莱斯忘记了

    public List<Module> SubModules { get; set; }
    

    虚拟的,如:

    public virtual List<Module> SubModules { get; set; }
    

    否则,EntityFramework在从数据库加载子级时无法为您预填充列表。因此,正确的代码是:

    public class Module
    {
        public Module()
        {
            SubModules = new List<Module>();
        }
    
        // Other properties
    
        public int? ParentModuleId { get; set; }
    
        [ForeignKey("ParentModuleId")]
        public virtual List<Module> SubModules { get; set; }
    }