Entity Framework 4.2 Code First 针对自关联表的操作办法

最近在学习并使用ASP.NET MVC3 + Entity Framework 4.2做项目,由于先前对EF的Code First不是很熟悉,所以在使用过程中遇到了不少的麻烦,其中遇到的第一个头痛的事情便是对自关联表(用于实现树状结构)的操作,还好最终解决了,现分享给大家。

首先,实体对象DemoEntity如下:

public class DemoEntity
{
public DemoEntity()
{
this.ChildEntitis = new HashSet<DemoEntity>(); //别忘了这里
}

[Key] //主键
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] //数据库生成默认值
public int Id { get; set; }

//父项Id,int?中的?声明表示该属性可为空值,与数据库表中的可空属性一致。
public int? ParentId { get; set; }

public string Name { get; set; }

//父实体对象,virtual表示延迟加载。
public virtual DemoEntity ParentEntity { get; set; }

//子实体对象集合,virtual表示延迟加载。
[ForeignKey("ParentId")] //指定子实体集合中的外键属性
public virtual ICollection<DemoEntity> ChildEntitis { get; set; }
}

 

然后是DbContext:

public class EFDbcontext : DbContext
{
public DbSet<DemoEntity> DemoEntitis { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//以下代码用于开启级联删除,但是针对自关联表只能删除第一层子数据,所以在此仅供大家参考
//modelBuilder.Entity<DemoEntity>()
// .HasOptional(e => e.ParentEntity)
// .WithMany(e => e.ChildEntitis)
// .WillCascadeOnDelete();
}
}


好了,接下来最坑爹的事情就要来到了,经过我的一番折腾,原本期望EF自身的级联删除功能能够方便的把任意实体对象及其子对象全部删除,但是没想到的是EF只能删除掉其第一层子数据,再多一层就会报错,百思不得其解之后查阅国外各种资料,发现EF和SQL Server对自关联表的级联删除是一样的:无法操作,所以只能采用笨办法了,递归出全部子数据然后反转删除:

private EFDbcontext context = new EFDbcontext();

public void DeleteWbsElement(DemoEntity demoEntity)
{
List<DemoEntity> list = new List<DemoEntity>();

CreateDeleteList(demoEntity, list);

list.Reverse(); //反转List中的对象顺序

list.ForEach(e => context.DemoEntitis.Remove(e)); //反向挨个删除

context.SaveChanges();
}

//递归所有子对象并将其加进泛型List
void CreateDeleteList(DemoEntity demoEntity, List<DemoEntity> list)
{
list.Add(demoEntity);

if (demoEntity.ChildEntitis.Count > 0)
{
foreach (DemoEntity element in DemoEntity.ChildEntitis)
{
CreateDeleteList(element, list);
}
}
}


不知道大家还有更好的办法没有,由于本人技术不深,不能十分确定其中原理,也希望高人能够赐教!

posted @ 2011-11-18 00:20  胡皓  阅读(3895)  评论(8编辑  收藏  举报