【问题标题】:EF6 Code First / Fluent API throwing error with Complex TypesEF6 Code First / Fluent API 引发复杂类型的错误
【发布时间】:2017-09-15 05:42:14
【问题描述】:

我在使用 EntityFramework 6 将复杂类型映射到模型类(称为 Assignment)时遇到问题。

我有以下Assignment模型类(仅显示相关成员):

public class Assignment
{ 
    private AssignmentDueByInfo _dueIn;

    public Assignment() {
         _dueIn = new AssignmentDueByInfo(this)
    }

    public virtual AssignmentSettingInfo DueIn
    {
        get { return _dueIn; }
        protected set { _dueIn = value; }
    }
}

其中AssignmentSettingInfo 定义为:

public class AssignmentSettingInfo
{
      protected AssignmentSettingInfo(Assignment assignment)
      {
           Assignment = assignment;
      }

      protected readonly Assignment Assignment;

      public virtual int? LessonId { get; protected set; }
      public virtual Lesson Lesson { get; protected set; }
}

在 Entity Framework 6 中,我将 Assignment 类的以下 CodeFirst / Fluent API 映射到数据库中的表:

Property(t => t.DueIn.LessonId).HasColumnName("DueByLessonId");

HasOptional(x => x.DueIn.Lesson)
            .WithMany(x => x.AssignmentsDue)
            .HasForeignKey(x => x.DueIn.LessonId)
            .WillCascadeOnDelete(true);

映射抛出以下错误:

表达式“x => x.DueIn.Lesson”不是有效的属性表达式。该表达式应表示一个属性:C#: 't => t.MyProperty'

为什么会发生这种情况,应该如何解决?

【问题讨论】:

  • 我认为这是 EF 的限制 - 复杂类型不能包含导航属性。

标签: c# entity-framework ef-code-first


【解决方案1】:

查看文档(它很旧,但仍然适用):

https://msdn.microsoft.com/en-us/library/bb738472(v=vs.100).aspx

这表明复杂类型不能包含导航属性。

我想这与它们没有主键并且它们不是由上下文单独管理的事实有关。如果它们没有 PK 并且无法通过上下文识别,则它们也不能是“关系结束”。

【讨论】:

    【解决方案2】:

    您正在尝试使 SQL 面向对象。您定义的代表数据库表的类应该是 POCO:相当简单的类,只有 get 和 set 属性。

    您在字段方面做得太多了。如果您必须在其中一个表类中填写字段,请三思。我从未见过表示数据库表的类需要任何字段的示例,而不是简单的 get/set 属性。

    如果其中一个类与另一个类相关,这是通过外键完成的,而不是通过this

    Assignment 类表示一个数据库表。该表应该具有某些列以及使用外键与其他表的关系。 Assignment 类不应包含不属于表的智能内容。

    例如,我看到Assignment 有一个名为_dueIn 的字段,类型为AssignmentDueByInfo。外人可以访问这个字段,但对他们来说这个字段不是AssignmentDueByInfo,而是AssignmentSettingInfo

    自行决定Assignment 应该有哪些列。

    是否有理由将 AssignmentSettingInfo 的列放在不同的表中?如果我查看您的代码,就不可能有AssignmentSettingInfo 没有'Assignmentand there can't be anAssignmentwithout anAssignmentSettingInfo`。那么为什么要把它们放在不同的表中呢?

    另一个问题是AssignmentSettingInfoLesson 之间的关系。这是零对一还是一对一? Follow these guide lines

    如果您将 'AssignmentandAssignmentSettingInfo` 放在一个表中,您的代码会是这样的

    class Assignment
    {
         public int Id {get; set;}
    
         // every assignment has exactly one AssignmentSettingInfo
         // use aggregation (in entity framework terms: complextype)
         public AssignmentSettingInfo AssignmentSettingInfo {get; set;}
    }
    
    [ComplexType]
    class AssignmentSettingInfo
    {
        // Every AssignmentSettingInfo has zero or one Lesson
        public virtual Lesson Lesson { get; set; }
    }
    

    课堂课程 { 公共 int ID {get;设置;}

        // relation between Line and AssignmentSettingInfo
        ...
    }
    

    我无法弄清楚LineAssignmentSettingInfo 之间的关系。访问:

    如果您真的希望 AssignmentSettingInfo 在不同的表中,请将其配置为一对一的方法,如链接所示

    【讨论】:

    • 拆分AssignmentSettingInfo 的原因是该类的功能比显示的要多,它在其他地方被重用。我更喜欢组合而不是继承。上面显示的类中删除了很多内容;这些字段的存在是有原因的,但超出了问题的范围。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 1970-01-01
    • 2016-01-09
    相关资源
    最近更新 更多