C# 实体框架:同一类型的多个集合

C# 实体框架:同一类型的多个集合,c#,entity-framework,ef-code-first,C#,Entity Framework,Ef Code First,我正在尝试创建一个包含两个相同类型集合的类。然而,当我阅读其中一个集合时,我从两个集合中都获得了数据。这意味着,我的Fluent API配置一定有问题 在LINQPad中,我可以看到集合“备选方案”和“答案”已经合并到一个“页面元素”集合中 示例代码 class Program { static void Main(string[] args) { var alternatives = new List<PageElement>

我正在尝试创建一个包含两个相同类型集合的类。然而,当我阅读其中一个集合时,我从两个集合中都获得了数据。这意味着,我的Fluent API配置一定有问题

在LINQPad中,我可以看到集合“备选方案”和“答案”已经合并到一个“页面元素”集合中

示例代码

class Program
{
    static void Main(string[] args)
    {
        var alternatives = new List<PageElement>
            {
                new PageElement {Data = "Alternative 1"},
                new PageElement {Data = "Alternative 2"},
                new PageElement {Data = "Alternative 3"},
                new PageElement {Data = "Alternative 4"},
            };

        var answers = new List<PageElement>
            {
                new PageElement { Data = "Answer 1" },
                new PageElement { Data = "Answer 2" },
            };

        var page = new Page
            {
                Alternatives = alternatives,
                Answers = answers
            };


        using (var context = new MyContext())
        {
            context.Pages.Add(page);
            context.SaveChanges();

            var loadedPage = context.Pages.First();

            foreach (var answer in loadedPage.Answers)
            {
                Console.WriteLine("Answer: " + answer.Data);
            }

        }


        Console.ReadLine();
    }
}



public class MyContext : DbContext
{
    public DbSet<Page> Pages { get; set; }

    public MyContext()
    {

    }

    protected override void OnModelCreating(DbModelBuilder mb)
    {

        mb.Entity<PageElement>()
          .HasRequired(p => p.Page)
          .WithMany(p => p.Alternatives)
          .HasForeignKey(p => p.PageId);

        mb.Entity<PageElement>()
          .HasRequired(p => p.Page)
          .WithMany(p => p.Answers)
          .HasForeignKey(p => p.PageId);

    }

}

public class Page
{
    public int Id { get; set; }
    public virtual ICollection<PageElement> Alternatives { get; set; }
    public virtual ICollection<PageElement> Answers { get; set; }
}

public class PageElement
{
    public int Id { get; set; }
    public int PageId { get; set; }
    public virtual Page Page { get; set; }

    public string Data { get; set; }
}
所需输出

Answer: Alternative 1
Answer: Alternative 2
Answer: Alternative 3
Answer: Alternative 4
Answer: Answer 1
Answer: Answer 2
Answer: Answer 1
Answer: Answer 2

这是因为您的备选方案和答案都存储在一个表中
PageElements
——即使您单独构建它们,但一旦它们进入数据库,它们就会一起保存。因此,当重新加载时,EF无法将它们分为两组

一个简单的解决方案是将它们分成两种类型,例如
AlternativeElement
AnswerElement
,这将创建两个表,从而避免问题

编辑

回答您的后续问题:您可以遵循派生类的模式,即使子类不添加新字段。然后使用该模式,这样您就只有一个数据库表,其中有一列指示每行所属的子类,因此:

public class PageElement
{
    public int Id { get; set; }
    public int PageId { get; set; }
    public virtual Page Page { get; set; }

    public string Data { get; set; }
}

public class PageElementAnswer : PageElement 
{
}

public class PageElementAlternative : PageElement 
{
}

public class Page
{
    public int Id { get; set; }
    public virtual ICollection<PageElementAlternative> Alternatives { get; set; }
    public virtual ICollection<PageElementAnswer> Answers { get; set; }
}
公共类页面元素
{
公共int Id{get;set;}
public int PageId{get;set;}
公共虚拟页页{get;set;}
公共字符串数据{get;set;}
}
公共类PageElement回答:PageElement
{
}
公共类PageElement可选:PageElement
{
}
公共类页面
{
公共int Id{get;set;}
公共虚拟ICollection替换项{get;set;}
公共虚拟ICollection答案{get;set;}
}

这是因为您的备选方案和答案都存储在一个表中
PageElements
——即使您单独构建它们,一旦它们进入数据库,它们就会一起保存。因此,当重新加载时,EF无法将它们分为两组

一个简单的解决方案是将它们分成两种类型,例如
AlternativeElement
AnswerElement
,这将创建两个表,从而避免问题

编辑

回答您的后续问题:您可以遵循派生类的模式,即使子类不添加新字段。然后使用该模式,这样您就只有一个数据库表,其中有一列指示每行所属的子类,因此:

public class PageElement
{
    public int Id { get; set; }
    public int PageId { get; set; }
    public virtual Page Page { get; set; }

    public string Data { get; set; }
}

public class PageElementAnswer : PageElement 
{
}

public class PageElementAlternative : PageElement 
{
}

public class Page
{
    public int Id { get; set; }
    public virtual ICollection<PageElementAlternative> Alternatives { get; set; }
    public virtual ICollection<PageElementAnswer> Answers { get; set; }
}
公共类页面元素
{
公共int Id{get;set;}
public int PageId{get;set;}
公共虚拟页页{get;set;}
公共字符串数据{get;set;}
}
公共类PageElement回答:PageElement
{
}
公共类PageElement可选:PageElement
{
}
公共类页面
{
公共int Id{get;set;}
公共虚拟ICollection替换项{get;set;}
公共虚拟ICollection答案{get;set;}
}

虽然这是一个真实而简单的解决方案,但我应该补充说,我希望在两个实体之间“共享”表,因为它们具有相同的签名。用一些Fluent的API配置就没有办法解决这个问题了吗?感谢您的回复:)虽然这是一个真实而简单的解决方案,但我应该补充说,我希望在两个实体之间“共享”表,因为它们具有相同的签名。用一些Fluent的API配置就没有办法解决这个问题了吗?感谢您的回复:)