1

考虑这种情况:

public class House
{
    public string Name { get; set; }
    public virtual Person Person1 { get; set; }
    public virtual Person Person2 { get; set; }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public House House { get; set; }
}

// Relationships
this.HasOptional(t => t.Person1)
    .WithRequired(t => t.House);
this.HasOptional(t => t.Person2)
    .WithRequired(t => t.House);

当我尝试插入 House 的实例时,会抛出 MetaDataException:

指定的架构无效。错误:(36,6):错误 0040:类型 House_Person1 未在命名空间 Company.Models 中定义(别名=Self)。

经过更多的黑客攻击,发现这可行:

// Relationships
this.HasOptional(t => t.Person1)
    .WithRequired();
this.HasOptional(t => t.Person2)
    .WithRequired();

但是我不会让 EF 填充 Person.House 属性。我可以模仿这种行为(如下所示)吗?

    public virtual Person Person1
    {
        get
        {
            return _person1;
        }
        set
        {
            _person1 = value;
            _person1.Haushalt = this;
        }
    }

    public virtual Person Person2
    {
        get
        {
            return _person2;
        }
        set
        {
            _person2 = value;
            _person2.Haushalt = this;
        }
    }
4

1 回答 1

2

您不能Person.House在两个不同的关系(House_Person1和)中使用相同的导航属性( House_Person2)。

另一个限制是 EF 仅支持将共享主键关联作为真正的一对一关系。这意味着一个相关HousePerson必须具有相同的主键值。但随之而来的是House.Person1House.Person2需要具有与House. 换句话说:Person1永远Person2不可能是不同的人。

我建议您将关系映射为一对多关系,并确保在应用程序的业务逻辑中 aHouse不能超过两个Persons。(因为您当前的映射允许Person1并且Person2是可选的,所以将允许零个或只允许一个人):

public class House
{
    public string Name { get; set; }
    public virtual ICollection<Person> People { get; set; }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public House House { get; set; }
}

this.HasMany(t => t.People)
    .WithRequired(t => t.House);

编辑

如果您想保留两个Person导航属性,House则只能将其映射为两个一对多关系(即使从业务角度来看这种关系是错误的)而没有导航属性(如此Person所示):

this.HasOptional(t => t.Person1)
    .WithMany();
this.HasOptional(t => t.Person2)
    .WithMany();

您可以像在上一个代码片段House中一样使用该属性Person,但您需要将其从模型中排除:

modelBuilder.Entity<Person>()
    .Ignore(t => t.House);

Person.House不再是导航属性,当您Person从数据库加载实体时,您无法加载它(使用急切或延迟加载)。

于 2012-10-18T18:03:55.360 回答