2
votes

I have an Item data model:

[DataContract]
public class Item
{
    [Key]
    [DataMember]
    public int ItemId { get; set; }

    [DataMember]
    public string Title { get; set; }

    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public ICollection<ItemImage> Images { get; set; }
}

and it links to ItemImage table through ItemId as foreign key:

[DataContract]
public class ItemImage
{
    [Key]
    [DataMember]
    public int ItemImageId { get; set; }

    [Required]
    [DataMember]
    public int ItemId { get; set; }

    [Required]
    [DataMember]
    public string ImageUrl { get; set; }

    [ForeignKey("ItemId")]
    public virtual Item Item { get; set; }
}

Everything works before I add the following code in

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
        modelBuilder.Entity<ItemImage>()
            .HasRequired(ii => ii.Item)
            .WithMany()
            .HasForeignKey(ii => ii.ItemId)
            .WillCascadeOnDelete(true);
}

After specify the cascade delete to true, the Images property in Item couldn't be loaded. Can someone help me figure out what is happening? Thanks a lot!

2

2 Answers

2
votes

You have that problem because you have missed the configuration of the many end in your relationship:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<ItemImage>()
        .HasRequired(ii => ii.Item)
        .WithMany(i=>i.Images)
        .HasForeignKey(ii => ii.ItemId)
        .WillCascadeOnDelete(true);
}

The first time it worked because EF uses the Data Annotations that you have applied (like ForeignKey) and by default EF recognizes that you want to create a one-to-many relationship due to the navigation properties that you have in both entities.

In addition, if a foreign key on the dependent entity (ItemImage) is not nullable, then Code First by default sets cascade delete on the relationship, so if you want, you don't need to use the Fluen Api configuration, your relationship was already set with cascade delete.

One last thing, if you want your navigation properties be lazy loaded, then you need to declare them as virtual:

[DataContract]
public class Item
{
    //...
    [DataMember]
    public virtual ICollection<ItemImage> Images { get; set; }
}
0
votes

try adding "virtual" so that you would get

public virtual ICollection<ItemImage> Images { get; set; }