如何以允许成功进行代码优先迁移的方式正确构建以下模型?

How do I properly structure the following models in a way that will allow a successful code first migration?

感谢观看。

我想创建以下 Image 域模型:

    [Table("Image")]    
    public class Image
    {
        [Key]
        public int Id { get; set; }
        [Required(ErrorMessage = "Please enter a title.")]
        public string Title { get; set; }
        [Required(ErrorMessage = "Please enter a caption.")]
        public string Caption { get; set; }
        [Required(ErrorMessage = "Please enter a file.")]
        public string File { get; set; }
    }

然后,我想让其他多个模型使用它。例如:

[Table("Product")]
public class Product
{
    [Key]
    public int Id { get; set; }
    [Required(ErrorMessage = "Please enter a title.")]
    public string Title { get; set; }
    [Required(ErrorMessage = "Please enter a description.")]
    public string Description { get; set; }
    public int ImageId { get; set; }
    public virtual Image Image { get; set; }       
}

[Table("User")]
public class User
{
    [Key]
    public int Id { get; set; }
    [Required(ErrorMessage = "Please enter a name.")]
    public string Name { get; set; }
    public int ImageId { get; set; }
    public virtual Image Image { get; set; }        
}

在管理(创建)ProductUser 时,我 确实 需要单个图像。此外,用于 ProductUser 的图像不会被任何其他实体使用。

问题

当我尝试通过程序包管理器控制台 (PM> update-database) 将此代码优先模型部署到数据库时,出现以下错误:

Introducing FOREIGN KEY constraint 'FK_dbo.Product_dbo.Image_ImageId' on table 'Product' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

因此返回的消息建议我更改 SQL 语句,这将不起作用,因为我是通过包管理器控制台/CodeFirst 自动执行此操作的。

问题

也就是说,我如何创建一个通用的 Image 实体模型,将其用作多个其他实体中的必需 属性,并且仍然通过 CodeFirst 部署而不违反 multiple cascade paths 规则?

提前致谢。

我一步一步地重现了你的场景,没有出现任何错误。但是,我相信你已经有一个现有的数据库,这可能会导致你上面描述的错误。

要解决 cycles or multiple cascade paths error,只需使用 Fluent API 映射关系,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>()
        .HasRequired(i => i.Image)
        .WithMany()
        .HasForeignKey(i => i.ImageId)
        .WillCascadeOnDelete(false);

    modelBuilder.Entity<User>()
        .HasRequired(i => i.Image)
        .WithMany()
        .HasForeignKey(i => i.ImageId)
        .WillCascadeOnDelete(false);

    base.OnModelCreating(modelBuilder);
}

我相信这应该足以解决您的问题。

你的第二个问题比较复杂:

When managing (creating) a Product or User I do want for a SINGLE image to be required. Also, the image used for Product or User will not be used by any other entity.

根据您当前的数据库结构,我看不出在数据库级别如何实现。我能想到的最简单的解决方法是:

  1. UsersProjects 创建一个单独的 Image 实体(如 UserImage、ProductImage)(我认为这不值得)
  2. 在应用程序级别验证关系

希望对您有所帮助!