单向级联删除与一对一或零关系

时间:2012-04-04 13:37:21

标签: entity-framework ef-code-first

我有一个实体,其中包含许多不同的文档,这些文档与我数据库中的任何实体都存在未知关系。

public class Document : BaseEntity
{

    public string Filename { get; set; }

    public string MIMEType { get; set; }
    public int? Length { get; set; }

    public byte[] Content { get; set; }

}

并且codefirst-mapping是:

    public DocumentConfiguration()
    {
        Property(x => x.Filename).HasMaxLength(300).IsRequired();
        Property(x => x.MIMEType).HasMaxLength(300).IsRequired();
        Property(x => x.Length).IsOptional();
        Property(x => x.Content).IsOptional().HasColumnType("varbinary(max)");


        ToTable("Document"); 
    }

现在我希望在我的地址中有一个与document-table的可选关系,如下所示:

public class Address : BaseEntity
{

    public string Name1 { get; set; }
    public string Name2 { get; set; }
    public string Additional { get; set; }


    public string Street { get; set; }
    public string HousNr { get; set; }
    public string ZipCode { get; set; }
    public string City { get; set; }

    public virtual Document Image { get; set; }

}

使用以下映射:

    public AddressConfiguration()
    {

        Property(x => x.Name1).IsRequired().HasMaxLength(250);
        Property(x => x.Name2).HasMaxLength(250);
        Property(x => x.Additional).HasMaxLength(250);


        Property(x => x.Street).HasMaxLength(250);
        Property(x => x.HousNr).HasMaxLength(10);
        Property(x => x.ZipCode).HasMaxLength(10);
        Property(x => x.City).HasMaxLength(100);


        HasOptional(x => x.Image)
            .WithOptionalDependent()
            .Map(map => map.MapKey("ImageId")).WillCascadeOnDelete();


        ToTable("Address");

    }

但是当我删除文档表中的图像时,它会删除相关的地址。

我想从地址到文档的OneWay-Deletation,但不是从文档到地址......?

我该如何实现?

谢谢。

2 个答案:

答案 0 :(得分:5)

从文档到地址具有级联的原因是因为您使用了WithOptionalDependent方法。来自文档:

  

将关系配置为可选:在关系的另一侧没有导航属性的可选项。正在配置的实体类型将是依赖项,并包含主体的外键。关系所针对的实体类型将是关系中的主体。

在AddressConfiguration方法中考虑这行代码:

HasOptional(x => x.Image)         // The entity type being configured is Address
   .WithOptionalDependent()...   // The entity type that the relationship targets
                                //  is Document (x.Image)

这意味着您有效地将Address指定为依赖关系,将Document指定为此关联中的主体,因此是级联行为。

但等等,这个故事还有更多内容!您可以通过两种方式创建一对一关联。首先是共享主键关联一对一外键关联。您可以从herehere了解更多相关信息。看起来您想要通过外键(一对一外键关联)映射您的关联。如果是这样,你必须注意,依赖实体将始终携带外键,这意味着在你的情况下,Document实体将有一个AddressId引用地址实体上的AddressId(你做了反向,这是不正确的。)。

所有这些,您的对象模型和流畅的API代码应如下所示:

public class Address 
{
    public int AddressId { get; set; }
    public virtual Document Image { get; set; }
}

public class Document 
{
    public int DocumentId { get; set; }
}

class Context : DbContext
{
    public DbSet<Address> Addresses { get; set; }
    public DbSet<Document> Documents { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Address>()  // The entity being configured is Address
                    .HasOptional(x => x.Image)  
                    .WithOptionalPrincipal()
                    .Map(map => map.MapKey("AddressId"))
                    .WillCascadeOnDelete();
    }
}

基本上WithOptionalPrincipal是您应该使用的方法:

  

将关系配置为可选:在关系的另一侧没有导航属性的可选项。正在配置的实体类型将是关系中的主体。关系所针对的实体类型将是依赖的实体类型,并包含主体的外键。


因此,从地址到文档正确地启用了级联删除。

答案 1 :(得分:0)

尝试删除OneToManyCascadeDeleteConvention:modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention >();