简体   繁体   English

EF CTP4级联删除多对多关系

[英]EF CTP4 cascade delete on many to many relationship

I've created a many to many relationship using default conventions in EF CTP4 by defining an ICollection on both image and project entities. 我通过在图像和项目实体上定义ICollection,使用EF CTP4中的默认约定创建了多对多关系。

The mapping table is created as below: 映射表创建如下:

create table [dbo].[Images_Project] (
[Images_Id] [uniqueidentifier] not null,
[Project_Id] [uniqueidentifier] not null,
primary key ([Images_Id]));

Unfortunately when I delete a project it is not cascading deletes to the image mapping table. 不幸的是,当我删除一个项目时,它不是级联删除到图像映射表。

I would expect EF to generate a key on both the Imanges_Id and Project_Id properties but this is not the case. 我希望EF能够在Imanges_Id和Project_Id属性上生成一个键,但事实并非如此。 How can I configure EF to delete the image mappings when a project is deleted? 如何在删除项目时配置EF以删除图像映射? (only the image mapping record, not the image record) (只有图像映射记录,而不是图像记录)

Thanks 谢谢

[Update] [更新]

Although cascade is apparently not possible, any idea why the following test passes: 虽然级联显然是不可能的,但任何想法为什么以下测试通过:

    [Test]
    public void Can_delete_project_with_images()
    {
        var project = new Project { Title = "Test project" };
        var image = new Image { Title = "Some image" };
        project.AddImage(image);
        context.Set<Project>().Add(project);
        context.SaveChanges();

        object id = project.Id;
        object imageId = image.Id;

        var fromDb = context.Projects.Find(id);
        fromDb.ShouldNotBeNull();
        context.Set<Project>().Remove(fromDb);
        context.SaveChanges();

        var fromDb2 = context.Images.Find(imageId);
        fromDb2.ShouldNotBeNull();
        fromDb2.Title.ShouldEqual("Some image");
    }

As of EF CTP4, there is no way to directly turn on cascade deletes on Many to Many associations in fluent API. 从EF CTP4开始,没有办法在流畅的API中直接打开多对多关联的级联删除。 The only way to have that is to explicitly put the link table into the object model: 唯一的方法是将链接表显式放入对象模型中:

public class Project
{
    public int Id { get; set; }    
    public ICollection<ProjectXrefImage> Images { get; set; }
}

public class ProjectXrefImage 
{
    [Key][DataMember(Order = 1)]
    public int ProjectId { get; set; }

    [Key][DataMember(Order = 2)]
    public int ImageId { get; set; }

    public Project Project { get; set; }
    public Image Image { get; set; }
}

public class Image 
{
    public int Id { get; set; }
    public virtual ICollection<ProjectXrefImage> Projects { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<Project> Projects { get; set; }
    public DbSet<Image> Images { get; set; }
    public DbSet<ProjectXrefImage> ProjectsXrefImages { get; set; }        
}

That said, I personally would not do this and will manually turn them on in the database. 也就是说,我个人不会这样做,并将在数据库中手动打开它们。

Update: 更新:

As you discovered it through your test case, code first will take care of cascade delete on the client side even though it's not turned on on the data store. 正如您通过测试用例发现的那样,代码首先会在客户端处理级联删除,即使它没有在数据存储上打开。 Which means, when you delete a Project by invoking Remove() method, code first is smart enough to first send a delete statement to get rid of the dependent record from the link table (Images_Projects) and after that it will send another delete statement to delete the project record. 这意味着,当您通过调用Remove()方法删除项目时,代码首先足够聪明,首先发送一个删除语句以从链接表(Images_Projects)中删除相关记录,之后它将发送另一个删除语句到删除项目记录。 I've verify that with SQL Profiler. 我用SQL Profiler验证了这一点。

That's why we can't turn on cascade deletes on many to many relationships, because we don't need it! 这就是为什么我们不能在多对多关系中打开级联删除,因为我们不需要它! The convention that I explained above will take care of that for us! 我上面解释的惯例将为我们处理!

SQL Server不允许您进行循环级联删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM