EF CTP4级联删除多对多关系 [英] EF CTP4 cascade delete on many to many relationship

查看:160
本文介绍了EF CTP4级联删除多对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



映射表创建为以下:

 创建表[dbo]。[Images_Project](
[Images_Id] [uniqueidentifier] not null,
[Project_Id] [uniqueidentifier]不为空,
主键([Images_Id]));

不幸的是,当我删除项目时,它不会级联删除到映像表。



我希望EF在Imanges_Id和Project_Id属性上生成一个键,但情况并非如此。删除项目时,如何配置EF删除图像映射? (仅图像映射记录,而不是图像记录)



感谢



[更新]



虽然级联显然是不可能的,但是为什么以下测试通过的任何想法:

  [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();

对象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);
}


解决方案

截至EF CTP4,没有办法直接在流畅的API中打开多对多关联的级联删除。唯一的方法是将链接表明确地放在对象模型中:

  public class Project 
{
public int Id {get;组; }
public ICollection< ProjectXrefImage>图片{get;组;
}

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

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

public Project Project {get;组; }
public Image Image {get;组; }
}

public class Image
{
public int Id {get;组; }
public virtual ICollection< ProjectXrefImage>项目{get;组; }
}

public class MyContext:DbContext
{
public DbSet< Project>项目{get;组; }
public DbSet< Image>图片{get;组; }
public DbSet< ProjectXrefImage> ProjectsXrefImages {get;组; }
}

这样说,我个人不会这样做,将手动将它们打开在数据库中。




更新:



当您通过测试用例发现即使数据存储没有打开,代码首先将在客户端进行级联删除。这意味着,当您通过调用Remove()方法删除项目时,代码首先是足够聪明的,首先发送删除语句以从链接表(Images_Projects)中删除相关记录,之后它将发送另一个delete语句删除项目记录。我已经通过SQL Profiler验证了。



这就是为什么我们无法打开多对多关系的级联删除,因为我们不需要它!我上面解释的惯例会照顾我们!


I've created a many to many relationship using default conventions in EF CTP4 by defining an ICollection on both image and project entities.

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. How can I configure EF to delete the image mappings when a project is deleted? (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. 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. I've verify that with 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!

这篇关于EF CTP4级联删除多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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