使用CTP4 Code-First删除实体 [英] Deleting entities with CTP4 Code-First

查看:61
本文介绍了使用CTP4 Code-First删除实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我正处于即将开始的新项目的架构高峰阶段,并且使用EF& amp;有几个关于实体删除的问题/疑虑。代码优先。我做了适量的搜索,但没有找到我正在寻找的
,所以如果我提出已经提出的问题,请提前道歉。

Hello, I am in the middle of an architecture spike for a new project that we are about to begin, and have a couple questions/concerns regarding entity deletion using EF & Code-First. I did a moderate amount of searching, and did not find what I'm looking for, so please accept my apologies in advance if I'm asking questions that have already been asked.

所以,在开始之前 - 这是我正在测试水域的小应用程序。这很简单 - 两个类,一个父母(Ticket) 与一个孩子有一对多的关系(TicketComment):

So, before getting started - here's the small app I'm testing the waters with. It is simple - two classes, a parent (Ticket) with a one-to-many relationship with a child (TicketComment):


public class Ticket {
 public Int32 Id { get; set; }
 public string Description { get; set; }
 public DateTime Created { get; set; }
 public virtual ICollection<TicketComment> Comments { get; set; }

 public Ticket() {
  Comments = new List<TicketComment>();
 }
 }
 public class TicketComment {
 public int Id { get; set; }
 public string Comment { get; set; }
 public DateTime Created { get; set; }
 public virtual Ticket Ticket { get; set; }
 }
And these entities are 'configured' for use with EF via these EntityConfiguration<T> subclasses:



internal class TicketConfiguration : EntityConfiguration<Ticket>{
 internal TicketConfiguration() {
  this.HasKey(t => t.Id);
  this.Property(t => t.Description).IsRequired();
  this.HasMany(t => t.Comments).WithRequired(tc => tc.Ticket).WillCascadeOnDelete();
 }
 }

 internal class TicketCommentConfiguration : EntityConfiguration<TicketComment> {
 internal TicketCommentConfiguration() {
  this.HasKey(tc => tc.Id);
this.MapSingleType(tc => new { tc.Id, tc.Comment, TICKETID = tc.Ticket.Id, CREATEDDATE = tc.Created }).ToTable("COMMENTS"); this.Property(tc => tc.Comment).IsRequired(); this.HasRequired(tc => tc.Ticket).WithMany(t => t.Comments).WillCascadeOnDelete(); } }

推荐答案

关于你的第一个问题,有实体当从父集合中删除它们时自动被删除不是EF当前支持的东西,但它是我们正在考虑的事情。 有一些东西你可以用b $ b来解决这个问题。 有一件事是调查RelatedEnd上的AssociationChanged事件,但这很难使用,特别是对于POCO实体。 您可以尝试的另一件事是为您的子集合
使用ObservableCollection,然后挂钩事件来处理被删除的项目。 例如,假设您有一个如此定义的实体:

With regards to your first question, having entities automatically get deleted when they are removed from a parent collection is not something that is currently supported by EF, but it is something we are thinking about.  There are a few things that you can do to work around this.  One thing is to look into the AssociationChanged event on RelatedEnd, but this is quite hard to use, especially with POCO entities.  Another thing you could try is using an ObservableCollection for your child collection and then hook up events to handle items being removed.  For example, imagine you have an entity defined like so:

 

 

public

团队
IHasChildCollections

{

   
private
readonly
ObservableCollection < 驱动程序 >
_drivers =
new
ObservableCollection < 驱动程序 >();
$


   
IEnumerable < INotifyCollectionChanged >
IHasChildCollections 。GetChildCollections()

    {

       
返回
new
列表 < INotifyCollectionChanged >
{_drivers};

   }



   
public
int
Id {
get ;
set ;
}

   
public
string
名称{
get ;
set ;
}



   
public

虚拟
ICollection < 驱动程序 >
司机

    {

       ; 
get
{
返回
_drivers;}

   }

}

public class Team : IHasChildCollections
{
   
private readonly ObservableCollection<Driver> _drivers = new ObservableCollection<Driver>();

   
IEnumerable<INotifyCollectionChanged> IHasChildCollections.GetChildCollections()
    {
       
return new List<INotifyCollectionChanged> { _drivers };
    }

   
public int Id { get; set; }
   
public string Name { get; set; }

    public virtual ICollection<Driver> Drivers
    {
       
get { return _drivers; }
    }
}

定义了这样的界面: 

With an interface defined like this: 

public
interface
IHasChildCollections

{

    IEnumerable < INotifyCollectionChanged >
GetChildCollections();

}

public interface IHasChildCollections
{
    IEnumerable<INotifyCollectionChanged> GetChildCollections();
}

现在当你创建您的上下文,您可以连接ObjectMaterialized事件以将ObservableCollections连接到EF状态管理器。例如:

Now when you create your context you can hook up the ObjectMaterialized event to connect the ObservableCollections to the EF state manager.  For example:

 

 

private
静态
void
HookUpOrphanDelete(
ObjectContext
context)

{

    context.ObjectMaterialized + =(s,e)=>

    {

       
var
hasChildren = e.Entity
as
IHasChildCollections ;

       
if
(hasChildren!=
null

        {

           
foreach
var
childCollection

hasChildren.GetChildCollections())

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; {

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;          childCollection.CollectionCha nged + =(CCS,CCE)=>

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; {

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;
如果
(cce.Action ==
NotifyCollectionChangedAction <跨度风格=" 字体家庭:索拉;字体 - 尺寸:x-small">。删除)

                 &NBSP;&NBSP;&NBSP; {

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;
foreach
var
已删除
< span style ="font-family:Consolas; font-size:x-small">
cce.OldItems)

                &nb属;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; {

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ;&NBSP;&NBSP;&NBSP;
ObjectStateEntry
stateEntry;

<跨度风格=" 颜色:#000000\" >&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;
如果
(( ObjectContext )3).ObjectStateManager.TryGetObjectStateEntry(除去,
<跨度风格="font-family:Consolas;颜色:#0000ff; font-size:x-small"> out

stateEntry)))
         ;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; {

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; stateEntry.ChangeState(
EntityState 。已删除);

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; &NBSP;&NBSP;&NBSP; }¥b $ b
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ;&NBSP;
}

&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP ; }
                }; b $ b            }
        }
    }
}

private static void HookUpOrphanDelete(ObjectContext context)
{
    context.ObjectMaterialized += (s, e) =>
    {
        var hasChildren = e.Entity as IHasChildCollections;
        if (hasChildren != null)
        {
            foreach (var childCollection in hasChildren.GetChildCollections())
            {
                childCollection.CollectionChanged += (ccs, cce) =>
                {
                    if (cce.Action == NotifyCollectionChangedAction.Remove)
                    {
                        foreach (var removed in cce.OldItems)
                        {
                            ObjectStateEntry stateEntry;
                            if (((ObjectContext)s).ObjectStateManager.TryGetObjectStateEntry(removed, out stateEntry))
                            {
                                stateEntry.ChangeState(
EntityState.Deleted);
                            }
                        }
                    }
                };
            }
        }
    };
}

这不是完美的,但它确实将您的实体保持为POCO并保持EF实施相对隔离的。请注意,此示例不包括重新生成父实体等内容,并且不处理
ObservableCollection可能向您抛出的所有不同CollectionChanged事件。 此外,由于事物被连接在ObjectMaterialized上,它意味着用"new"创建的实体。并且添加到上下文中不会自动连接,所以如果它对您的应用程序很重要,那么您必须做一些特殊处理
的情况。

This isn't perfect, but it does keep your entities as POCO and keeps the EF implementation relatively isolated. Note that this example doesn't cover things like re-parenting entities, and doesn't handle all the different CollectionChanged events that the ObservableCollection might throw at you.  Also, since things get hooked up on ObjectMaterialized it means that entities created with "new" and Added to the context won't get automatically hooked up, so you would have to do something special to handle that case if it is important for your app.

关于问候对于你的第二个问题,Cascade Delete背后的想法是你的数据库中也有一条规则,删除委托人时会删除家属。 这意味着当您在没有加载dependents的
的情况下删除数据库中的主体时,数据库将负责删除相关行。

With regards to your second question, the idea behind Cascade Delete is that you also have a rule in your database that will delete dependents when the principal is deleted.  This means that when you do the delete of the principal in the database without having the dependents loaded the the database will take care of removing the dependent rows.

希望这会有所帮助。

谢谢,

亚瑟

Thanks,
Arthur

 


这篇关于使用CTP4 Code-First删除实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆