B Z*_*B Z 14 entity-framework entity-framework-5
EF 5.0
我正在研究一个原型来一起测试hierarchyid和实体框架.我有以下架构:
Create Table dbo.Employee
(
EmployeeId int identity not null,
Name nvarchar(100) not null,
Node hierarchyid not null,
NodePath as Node.ToString() persisted,
Level AS Node.GetLevel() persisted,
ManagerNode as Node.GetAncestor(1) persisted,
ManagerNodePath as Node.GetAncestor(1).ToString() persisted
);
Alter Table dbo.Employee
Add Constraint EmployeePK Primary Key NonClustered (EmployeeId);
Go
--Enforce Hierarchy
Alter Table dbo.Employee
Add Constraint EmployeeManagerNodeNodeFK Foreign Key (ManagerNode) References Employee(Node);
Go
Create Unique Clustered Index EmployeeDepthFirstIndex on dbo.Employee(Node);
Go
Create NonClustered Index EmployeeBreathFirstIndex on dbo.Employee(Level, Node);
Go
Run Code Online (Sandbox Code Playgroud)
从我的阅读中,EF目前不支持hierarchyid数据类型,但是有些人提出了一些变通方法,例如创建我上面已经完成的计算列(Node.ToString()).
有没有办法设置EF,以便它识别父/子关系,这样我可以有效地拥有一个下属集合?例如
Employee.Subordinates
Run Code Online (Sandbox Code Playgroud)
我唯一能想到的是创建一个带有FK的ManagerId列,但后来我有效地将层次结构存储在两个地方.
谢谢你的帮助!
小智 21
EF6现在是开源的,因此很容易添加HierarcyID支持.我也加了它.您可以从codeplex下载修改后的源代码和编译/签名的dll:http: //entityframework.codeplex.com/SourceControl/network/forks/zgabi/efhierarchyidrc1(有时候fork名称更改)或者来自NuGet:https:// www .nuget.org/packages/EntityFrameworkWithHierarchyId / Currenty EF6处于RC1状态,但我会将修改合并到EF6的每个后续版本中.
我有以下型号:
public class Employee
{
public int EmployeeId { get; set; }
[Required, MaxLength(100)]
public string Name { get; set; }
[Required]
public HierarchyId Node { get; set; }
public IQueryable<Employee> GetSubordinates(MyContext context)
{
return context.Employees.Where(o => Node == o.Node.GetAncestor(1));
}
}
public class MyContextInitializer : CreateDatabaseIfNotExists<MyContext>
{
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<Employee> Employees { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
生成的数据库:
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])
Run Code Online (Sandbox Code Playgroud)
获取Emp1员工子节点的示例:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
4 Emp3
7 Emp6
Run Code Online (Sandbox Code Playgroud)
小智 5
使用varbinary(892)代替architectureid。EF识别varbinary返回的字节数组。您可以将字节数组转换为SqlHierarchyid类型,并使用hyrarchy pod函数。通过这种解决方法,您甚至可以在其他数据库中使用architectureid函数。请参阅http://www.casavillar.com.br/blog,以获取更多详细信息以及指向nugget和github的链接,您将在其中找到包括MySql在内的示例
| 归档时间: |
|
| 查看次数: |
12672 次 |
| 最近记录: |