2

这让我觉得自己像个白痴。实体框架应该相当简单,但我自己无法解决这个问题,显然我有一个基本的误解。我希望这不是一个白痴问题——如果是的话,对不起。

三个相互关联的代码优先对象。

public class Schedule
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid RowId { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }

    public virtual ICollection<Charge> Charges { get; set; }
}

public class Charge
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid RowId { get; set; }
    public decimal Rate { get; set; }
    public Type Type { get; set; }
}

public class Type
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid RowId { get; set; }
    public string TypeName { get; set; }
}

当我查询这个时,我想要所有相关类型,所以:

        Schedule currentSchedule = _Context.Schedules
                .Include("Charges.Type")
                .Where(cs => cs.Start < dateWindow && cs.End > dateWindow)
                .First();

在 C# 中,这一直运行良好。

问题的出现是因为我们没有停留在 C# 上,而是将数据传递到一个名为 Breeze 的 javascript 库中,从而平滑了客户端的数据操作。Breeze 有一个错误/功能,它要求在 BOTH ENDS 指定对象之间的 EF 关系。所以当我在上面进行查询时,我没有得到任何类型,因为没有直接指定它们与 Charge 的关系。

所以我把它改成这样:

public class Type
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid RowId { get; set; }
    public string TypeName { get; set; }
    public virtual Charge Charge { get; set; }
}

因为 virtual 是一个导航属性,所以这应该使 Breeze 现在应该在不改变数据结构的情况下双向跨越关系。但 EF 不喜欢这样。它告诉我:

无法确定类型“Core.Charge”和“Core.Type”之间关联的主体端。此关联的主体端必须使用关系流式 API 或数据注释显式配置

很公平。我可以看到这可能会令人困惑。现在,我的理解是,如果您在依赖类中定义外键,它必须是该类的主键。所以我们把它改成:

public class Type
{
    [Key, ForeignKey("Charge"), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid RowId { get; set; }
    public string TypeName { get; set; }
    public virtual Charge Charge { get; set; }
}

这似乎可行,但是......当您要求安排时,它会停止加载任何类型信息。搞乱包含似乎根本没有做任何事情。

发生了什么事,我做错了什么?

4

2 回答 2

2

您不仅向Type.Charge现有模型/关系添加了导航属性 ( )。相反,您已将关系从一对多完全更改为一对一关系,因为默认情况下,如果关系只有一个导航属性,则 EF 假定为一对多关系。通过您的更改,您已经配置了一对一的关系。

这些关系有不同的外键:原始的一对多关系在Charge表中有一个单独的外键(可能命名Type_RowId或类似)。您的新关系在表的另一端有外键,Type它是主键RowIdCharge您与 s 一起加载的sSchedule可能Type与相同的主键没有任何关系,因此没有Type加载。

如果您真的想在另一侧仅使用导航属性重现旧的(一对多)关系,则必须添加一个集合Type而不是单个引用:

public class Type
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid RowId { get; set; }
    public string TypeName { get; set; }
    public virtual ICollection<Charge> Charges { get; set; }
}
于 2013-07-19T14:14:44.683 回答
0

你确定要将ForeignKey放在RowId上吗,我想你可能想定义一些这样的关系

public class Type
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid RowId { get; set; }
    public string TypeName { get; set; }
    public int ChargeId { get; set; }
    [ForeignKey("ChargeId")]
    public virtual Charge Charge { get; set; }
}
于 2013-07-19T14:08:04.053 回答