0

我有一个 POCO 代码优先模型,它需要有效的递归引用。当我尝试创建实体时,我根据标题收到“角色更改冲突...”错误。

这里有一组简化的类来说明这个问题:

    public class Master
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Query2 Query { get; set; }
}
public class Query2
{
    public Query2()
    {
        Columns = new List<Column2>();
    }
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Column2> Columns { get; set; }
}
public class Column2
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Query2 Query { get; set; }
}

属性 Column2.Query 存在问题。

这是生成自动样本数据的代码:

    public class TestContext : DbContext
{
    public TestContext()
    {
        this.Configuration.LazyLoadingEnabled = false;
    }

    public DbSet<Master> Masters { get; set; }
    public DbSet<Query2> Queries { get; set; }
    public DbSet<Column2> Columns { get; set; }
}
public class TestContextInitializer : DropCreateDatabaseIfModelChanges<TestContext>
{
    protected override void Seed(TestContext context)
    {
        Master master = new Master() { Name = "Test" };
        master.Query = new Query2() { Name = "Query1" };
        Column2 col = new Column2() { Name = "Column1" };
        master.Query.Columns.Add(col);
        col.Query = new Query2() { Name = "Query2" };
        col.Query.Columns.Add(new Column2() { Name = "Column2" });
        context.Masters.Add(master);
    }
}

这会引发错误:

        private void Test2()
    {
        ZapDatabase(@"D:\Visual Studio\TestDPDatabase\TestDPDatabase\TestContext.sdf");
        System.Data.Entity.Database.SetInitializer<TestContext>(new TestContextInitializer());
        using (TestContext cont = new TestContext())
        {
            var result = cont.Masters.Include("Query").Include("Query.Columns").Include("Query.Columns.Query").Include("Query.Columns.Query.Columns").ToList();
            int objects = result.Count;
        }
    }

我检查了许多报告此错误并寻求解决方案的人的实例,所有这些我都能理解答案,但没有一个具有这种递归结构。

非常感谢您提供的任何帮助。

4

2 回答 2

0

解决方案是明确关系的两端并添加如下映射:

    public class Master
{
    [Key()]
    public int MasterId { get; set; }
    public string Name { get; set; }
    public virtual Query2 Query { get; set; }
}
public class Query2
{
    public Query2()
    {
        Columns = new List<Column2>();
    }
    [Key()]
    public int QueryId { get; set; }
    public string Name { get; set; }
    public virtual Master Master { get; set; }
    public virtual ICollection<Column2> Columns { get; set; }
}
public class Column2
{
    [Key()]
    public int ColumnId { get; set; }
    public string Name { get; set; }
    public virtual Query2 Query { get; set; }
    public virtual Query2 ColQuery { get; set; }
}

和映射

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Query2>().HasRequired(q => q.Master).WithRequiredPrincipal(m => m.Query);
    }

作为 EF 新手,我的感觉是明确而不是依赖默认值更好。

于 2013-05-17T07:31:59.083 回答
0

我认为问题在于您在Seed()方法中创建的实体与 EF 推断的关系冲突。默认情况下,当你有类似的东西时

public class Query2
{
  ...
  public virtual ICollection<Column2> Columns { get; set; }
}

public class Column2
{
  ...
  public virtual Query2 Query { get; set; }
}

... EF 假设这是一种互惠关系。因此,当您添加colmaster.Query.Columns,但设置col.Query为新实例时,它不喜欢它 - 关系不满足。

如果这不是您希望关系工作的方式,您可能必须OnModelCreating()在您的中覆盖DbContext并使用 Fluent API 来定义应该如何设置事物。

于 2013-05-16T14:45:58.097 回答