使用多对多和一对多到同一个实体 [英] Using both many-to-many and one-to-many to same entity

查看:119
本文介绍了使用多对多和一对多到同一个实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在EF Code-First中有多对多关联(如这个问题),我想要使用一对多到同一个实体。问题是EF不产生正确的数据库方案。代码:

  public class A 
{
public int Id {get;组; }
public string Name {get;组; }
public virtual ICollection< B> ObjectsOfB {get;组; }
}

public class B
{
public int Id {get;组; }
public virtual A ObjectA {get;组; }
public virtual ICollection< A> OtherObjectsOfA {get;组; }
}

当我删除B类的ObjectA属性时,多对多关联正确生成。
当生成不正确时,实体B得到2个外键到A,实体A获得1个外键到B(如多对一关系)。

解决方案

如果您有多个导航属性引用同一个实体,EF不知道另一个实体所属的反向导航属性的位置。在你的例子中: A.ObjectsOfB 参考 B.ObjectA B.OtherObjectsOfA ?两者都是可能的,并且是一个有效的模型。



现在,EF并没有抛出像无法明确确定关系等异常。相反,它决定 B.ObjectA 是指在 B 中的第三个端点,它不会作为模型中的导航属性公开。这将在表 B 中创建第一个外键。 B 中的两个导航属性指的是 A 中的两个端点,它们也不会在模型中公开: B.ObjectA 在表 B 中创建第二个外键B.OtherObjectsOfA 在表 A 中创建一个外键。



要解决这个问题,您必须明确指定关系。 >

选项一(最简单的方法)是使用 InverseProperty 属性:

  public class A 
{
public int Id {get;组; }
public string Name {get;组; }
[InverseProperty(OtherObjectsOfA)]
public virtual ICollection< B> ObjectsOfB {get;组; }
}

这定义了 A.ObjectsOfB 是与 B.OtherObjectsOfA 的多对多关系的一部分。



另一个选项是在Fluent API中完全定义关系:

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity< A>()
.HasMany(a => a.ObjectsOfB)
.WithMany(b => b.OtherObjectsOfA)
.Map(x =>
{
x.MapLeftKey(AId);
x.MapRightKey(BId);
x.ToTable(ABs);
}) ;

modelBuilder.Entity< B>()
.HasRequired(b => b.ObjectA)//或HasOptional
.WithMany()
.WillCascadeOnDelete(假); //不确定如果有必要,可以试试
//如果你想要级联删除
}


I have a many-to-many association in EF Code-First (as explained in this question), and I want to use a one-to-many to the same entity as well. The problem is EF does not produce the right database scheme. Code:

public class A
{
  public int Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<B> ObjectsOfB { get; set; }
}

public class B
{
  public int Id { get; set; }
  public virtual A ObjectA { get; set; }
  public virtual ICollection<A> OtherObjectsOfA { get; set; }
}

When I remove the ObjectA property of class B the many-to-many association is generated correctly. When generated incorrectly, entity B gets 2 foreign keys to A, and entity A gets 1 foreign key to B (like a many-to-one relation).

解决方案

If you have more than one navigation property refering to the same entity EF does not know where the inverse navigation property on the other entity belongs to. In your example: Does A.ObjectsOfB refer to B.ObjectA or to B.OtherObjectsOfA? Both would be possible and a valid model.

Now, EF does not throw an exception like "cannot determine relationships unambiguously" or something. Instead it decides that B.ObjectA refers to a third endpoint in B which is not exposed as navigation property in the model. This creates the first foreign key in table B. The two navigation properties in B refer to two endpoints in A which are also not exposed in the model: B.ObjectA creats the second foreign key in table B and B.OtherObjectsOfA creates a foreign key in table A.

To fix this you must specify the relationships explicitely.

Option one (the easiest way) is to use the InverseProperty attribute:

public class A
{
    public int Id { get; set; }
    public string Name { get; set; }
    [InverseProperty("OtherObjectsOfA")]
    public virtual ICollection<B> ObjectsOfB { get; set; }
}

This defines that A.ObjectsOfB is part of a many-to-many relation to B.OtherObjectsOfA.

The other option is to define the relationships completely in Fluent API:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<A>()
        .HasMany(a => a.ObjectsOfB)
        .WithMany(b => b.OtherObjectsOfA)
        .Map(x =>
        {
            x.MapLeftKey("AId");
            x.MapRightKey("BId");
            x.ToTable("ABs");
        });

    modelBuilder.Entity<B>()
        .HasRequired(b => b.ObjectA)  // or HasOptional
        .WithMany()
        .WillCascadeOnDelete(false);  // not sure if necessary, you can try it
                                      // without if you want cascading delete
}

这篇关于使用多对多和一对多到同一个实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆