EF核心:循环实体参考

时间:2017-06-16 08:00:10

标签: c# asp.net-core entity-framework-core

我想说要了解ASP.NET Core以了解如何使用webforms实现以前的版本,需要花费大量时间,但我知道ASP.NET Core更大,你可以构建更多复杂的解决方案。

我是ASP.NET Core的新手,我试图理解EF Core和相关数据。我使用https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro来学习基础知识并创建我的第一个ASP.NET核心应用程序。

我有一个实体"标准"可以有多个表单(表单实体)。实体共享几个相同的属性,因此我们使它们都从名为MasterDocument的主类继承。以前称为Document。

标准

namespace Skjemabasen.Models.Document
{
    public class Standard : MasterDocument
    {
        [Display(Name = "Kategori")]
        public virtual Category Category { get; set; }
        [Display(Name = "Dokumenter")]
        public ICollection<Form> Forms { get; set; }
    }
}

形式:

public class Form : MasterDocument
{
    public Format Format { get; set; }
    public virtual Member Assignee { get; set; }
    public String Status { get; set; }
    [ForeignKey("Standard")]
    public int StandardId { get; set; }
    public Standard Standard { get; set; }
    public ICollection<Customer.Subscription> Subscribers { get; set; }
}

MasterDocument:

namespace Skjemabasen.Models.Document
{
    public class MasterDocument : IDocument
    {       
        public int ID { get; set; }
        [Required]
        [Display(Name = "EStandard")]
        [StringLength(50)]
        public string EStandard { get; set; }
        [Required]
        [Column("Betegnelse")]
        [Display(Name = "Betegnelse")]
        [StringLength(60)]
        public string Betegnelse { get; set; }
        [Display(Name = "Kommentar")]
        public string Comment { get; set; }
    }
}

据我所知,这会导致循环请求或循环删除,因此我在标准版上插入了DeleteBehavior.Restrict

        modelBuilder.Entity<Standard>()
            .HasOne(d => d.Forms)
            .WithMany()
            .OnDelete(DeleteBehavior.Restrict);

我的完整上下文课程:

namespace Skjemabasen.Data
{
    public class SkjemabasenContext : DbContext
    {
        public SkjemabasenContext(DbContextOptions<SkjemabasenContext> options) :base(options)
        {

        }

        public DbSet<Member> Members { get; set; }
        public DbSet<Category> Categories { get; set; }
        public DbSet<Standard> Standards { get; set; }
        public DbSet<Form> Forms { get; set; }
        public DbSet<Customer> Customers { get; set; }
        public DbSet<Revision> Revisions { get; set; }
        public DbSet<Subscription> Subscriptions { get; set; }
        public DbSet<MasterDocument> Documents { get; set; }

        public IQueryable<Customer> CurrentCustomers
        {
            get { return Customers.Where(c => c.Inactive == false); }
        }

        public IQueryable<Customer> InActiveCustomers
        {
            get { return Customers.Where(c => c.Inactive == true); }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            modelBuilder.Entity<Member>().ToTable("Member");
            modelBuilder.Entity<Category>().ToTable("Category");
            modelBuilder.Entity<Standard>().ToTable("Standard");
            modelBuilder.Entity<Form>().ToTable("Form");
            modelBuilder.Entity<Customer>().ToTable("Customer");
            modelBuilder.Entity<Revision>().ToTable("Revision");
            modelBuilder.Entity<Subscription>().ToTable("Subscription");
            modelBuilder.Entity<MasterDocument>().ToTable("Document");


            modelBuilder.Entity<Standard>()
                .HasOne(d => d.Forms)
                .WithMany()
                .OnDelete(DeleteBehavior.Restrict);
        }
    }
}

当我尝试运行应用程序时,我收到错误:

  

System.ArgumentException:&#39;实体类型   &#39; System.Collections.Generic.ICollection`1 [Skjemabasen.Models.Document.Form]&#39;   提供参数&#39; clrType&#39;必须是参考类型。&#39;因为   所有表格必须有一个父母标准,并且两者都必须有标准&#39;和&#39;形式&#39;   继承自MasterDocument,据我所知ASP.NET Core警告   关于循环删除,但我不知道如何实现这一点。该   关于ICollection&#39; Forms&#39;不是一个   参考类型。标准&#39;标签&#39;与...有关   形式与&#39;之间的关系。

基于https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro,我无法弄清楚我在这里失踪了什么。

1 个答案:

答案 0 :(得分:0)

我假设您实际上并不希望通过继承MasterDocument来拥有多态实体。因此,从我看到的,您希望Form和Standard共享MasterDocument的相同属性,而MasterDocument本身就是一个实体。如果是这种情况,只需将这些属性抽象为基类:

public abstract class MasterBaseDocument
{       
    public int ID { get; set; }
    [Required]
    [Display(Name = "EStandard")]
    [StringLength(50)]
    public string EStandard { get; set; }
    [Required]
    [Column("Betegnelse")]
    [Display(Name = "Betegnelse")]
    [StringLength(60)]
    public string Betegnelse { get; set; }
    [Display(Name = "Kommentar")]
    public string Comment { get; set; }
}

public class Form : MasterBaseDocument
{
    ...
}
public class Standard : MasterBaseDocument
{
    ...
}

public class MasterDocument : MasterBaseDocument
{
    // right now, empty here...
}

那应该解决它。

您的模型的另一种方法是在Forms和Standard上拥有MasterDocument FK。这样你就不会在表格上得到重复字段。

进一步改进:另外,请记住,您可以使用FluentAPI使用属性实现所有这些配置。这样你的类就可以保存并与EF的东西分离。这只会增加噪音并使其难以阅读。应该是关于EF文档的Fluent API的示例。