Entity framework 实体框架层次结构解决方案
EF 5.0 我正在开发一个原型来共同测试hierarchyid和实体框架。我有以下模式:Entity framework 实体框架层次结构解决方案,entity-framework,entity-framework-5,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() persist
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
据我所知,目前EF中不支持hierarchyid数据类型,但一些人建议了一些解决方法,如创建计算列(Node.ToString()),我在上面已经做过
是否有一种方法可以设置EF,使其能够识别父/子关系,从而有效地拥有下属集合?e、 g
Employee.Subordinates
我唯一能想到的是创建一个带有FK的ManagerId列,但是我实际上是在两个地方存储层次结构
谢谢你的帮助 EF6现在是开源的,所以添加层次结构支持很容易。我也加了。 您可以从codeplex下载已修改的源代码和已编译/已签名的DLL: (有时fork名称会更改) 或者来自NuGet: 当前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; }
}
获取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);
}
}
结果:
4 Emp3
7 Emp6
使用varbinary(892)代替hierarchyid。
EF识别varbinary返回字节数组。
您可以将字节数组转换为SqlHierarchyid类型,并使用hyrarchy pod函数。
通过这种解决方法,您甚至可以在其他数据库中使用hierarchyid函数。
请参阅更多详细信息和指向nugget和github的链接,在那里您可以找到包括MySql在内的示例@zgabi好奇为什么这没有成为正式版本???@BZ-实体框架团队认为层次结构支持的需求不足以实现它,显然,他们最近如何实现其他类似类型的应用程序存在一些复杂问题,他们希望避免这些问题,而是使用某种扩展框架来处理这些问题。但他们没有时间进行6 RTM。可能在将来的更新中:(不幸的是,其他二进制文件依赖于具有特定公钥的EF(ASP.NET标识),这意味着不可能始终使用此库。@zgavi,repo的问题在于它是一个fork,而不是一个扩展。它已合并到官方EF中,因此公钥问题将在以下版本中解决。
4 Emp3
7 Emp6