Entity Framework HierarchyId Workarounds

后端 未结 2 656
隐瞒了意图╮
隐瞒了意图╮ 2020-12-13 07:38

EF 5.0

I am working on a prototype to test hierarchyid and entity framework together. I have the following schema:

Create Table dbo.Employee
(
   Emp         


        
2条回答
  •  离开以前
    2020-12-13 08:17

    EF6 is now open source, so it is easy to add HierarcyID support. I have added it, too. You can download the modifed source and the complied/signed dlls from codeplex: http://entityframework.codeplex.com/SourceControl/network/forks/zgabi/efhierarchyidrc1 (sometimes the fork name changes) Or from NuGet: https://www.nuget.org/packages/EntityFrameworkWithHierarchyId/ Currenty EF6 is in RC1 state, but I'll merge the modifications to every later releases of EF6.

    I have the following model:

    public class Employee
    {
        public int EmployeeId { get; set; }
        [Required, MaxLength(100)]
        public string Name { get; set; }
        [Required]
        public HierarchyId Node { get; set; }
    
        public IQueryable GetSubordinates(MyContext context)
        {
            return context.Employees.Where(o => Node == o.Node.GetAncestor(1));
        }
    }
    
    public class MyContextInitializer : CreateDatabaseIfNotExists
    {
        protected override void Seed(MyContext context)
        {
            context.Database.ExecuteSqlCommand(
                "ALTER TABLE [dbo].[Employees] ADD [ManagerNode] AS ([Node].[GetAncestor]((1))) PERSISTED");
            context.Database.ExecuteSqlCommand(
                "ALTER TABLE [dbo].[Employees] ADD CONSTRAINT [UK_EmployeeNode] UNIQUE NONCLUSTERED (Node)");
            context.Database.ExecuteSqlCommand(
                "ALTER TABLE [dbo].[Employees]  WITH CHECK ADD CONSTRAINT [EmployeeManagerNodeNodeFK] " +
                "FOREIGN KEY([ManagerNode]) REFERENCES [dbo].[Employees] ([Node])");
            context.Employees.Add(new Employee { Name = "Root", Node = new HierarchyId("/") });
            context.Employees.Add(new Employee { Name = "Emp1", Node = new HierarchyId("/1/") });
            context.Employees.Add(new Employee { Name = "Emp2", Node = new HierarchyId("/2/") });
            context.Employees.Add(new Employee { Name = "Emp3", Node = new HierarchyId("/1/1/") });
            context.Employees.Add(new Employee { Name = "Emp4", Node = new HierarchyId("/1/1/1/") });
            context.Employees.Add(new Employee { Name = "Emp5", Node = new HierarchyId("/2/1/") });
            context.Employees.Add(new Employee { Name = "Emp6", Node = new HierarchyId("/1/2/") });
        }
    }
    
    public class MyContext : DbContext
    {
        public DbSet Employees { get; set; }
    }
    

    Generated database:

    CREATE TABLE [dbo].[Employees](
        [EmployeeId] [int] IDENTITY(1,1) NOT NULL,
        [Name] [nvarchar](100) NOT NULL,
        [Node] [hierarchyid] NOT NULL,
        [ManagerNode]  AS ([Node].[GetAncestor]((1))) PERSISTED,
     CONSTRAINT [PK_dbo.Employees] PRIMARY KEY CLUSTERED 
    (
        [EmployeeId] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
     CONSTRAINT [UK_EmployeeNode] UNIQUE NONCLUSTERED 
    (
        [Node] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    
    ALTER TABLE [dbo].[Employees]  WITH CHECK ADD  CONSTRAINT [EmployeeManagerNodeNodeFK] FOREIGN KEY([ManagerNode])
    REFERENCES [dbo].[Employees] ([Node])
    

    Example to get the child nodes of Emp1 employee:

        using (var c = new MyContext())
        {
            var firstItem = c.Employees.Single(o => o.Node == new HierarchyId("/1/"));
    
            foreach (var table1 in firstItem.GetSubordinates(c))
            {
                Console.WriteLine(table1.EmployeeId + " " + table1.Name);
            }
        }
    

    result:

    4 Emp3
    7 Emp6
    

提交回复
热议问题