C#EF6实体映射

时间:2018-03-31 18:05:10

标签: c# .net entity-framework ef-fluent-api

我目前正在开发一个应该将EF6与MySql数据库一起使用的项目(WCF服务)。该部分本身已经正常工作,但我在映射方面存在很大问题。

我有3个实体,如下所示:

Employee - ManyToMany - Project - OneToMany - ProjectStep

我的数据库模型设置如下:

员工表:

CREATE TABLE `employee` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Name` varchar(255) DEFAULT NULL,
  `JobDescription` varchar(255) DEFAULT NULL,
  `Department` varchar(255) DEFAULT NULL,
  `DirectDialing` varchar(255) DEFAULT NULL,
  `Status` bit(1) DEFAULT NULL,
  PRIMARY KEY (`ID`)
)

项目表:

CREATE TABLE `project` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Titel` varchar(255) DEFAULT NULL,
  `StartDate` datetime DEFAULT NULL,
  `EndDate` datetime DEFAULT NULL,
  `Description` varchar(255) DEFAULT NULL,
  `ProjectLeader` int(11) DEFAULT NULL,
  `Status` int(11) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  CONSTRAINT `project_fk` FOREIGN KEY (`ProjectLeader`) REFERENCES `employee` (`ID`)
)

ProjectStep表:

CREATE TABLE `project_step` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Description` text,
  `StartDate` datetime DEFAULT NULL,
  `EndDate` datetime DEFAULT NULL,
  `Project` int(11) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  CONSTRAINT `project_step_fk` FOREIGN KEY (`Project`) REFERENCES `project` (`ID`)
)

映射表Employee - Project

CREATE TABLE `employee_project` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `EmployeeId` int(11) DEFAULT NULL,
  `ProjectId` int(11) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  CONSTRAINT `projectId_fk` FOREIGN KEY (`ProjectId`) REFERENCES `project` (`ID`)
  CONSTRAINT `employeeId_fk` FOREIGN KEY (`EmployeeId`) REFERENCES `employee` (`ID`)
)

然后,我创建了如下实体:

[DataContract(Namespace = "Shared")]
public class Employee
{
    public Employee()
    {
        this.Projects = new List<Project>();
    }

    [DataMember]
    [Key]
    public int ID { get; set; }

    [DataMember]
    public String Name { get; set; }

    [DataMember]
    public String Berufsbezeichnung { get; set; }

    [DataMember]
    public String Abteilung { get; set; }

    [DataMember]
    public String Durchwahl { get; set; }

    [DataMember]
    public bool Status { get; set; }

    [DataMember]
    public virtual ICollection<Project> Projects { get; set; }
}

[DataContract(Namespace = "Shared")]
public class Project
{

    public Project()
    {
        this.EmployeesWorkingOnProject = new List<Employee>();
        this.ProjectSteps = new List<ProjectStep>();
    }

    [DataMember]
    [Key]
    public int ID { get; set; }

    [DataMember]
    public String Titel { get; set; }

    [DataMember]
    public DateTime StartDatum { get; set; }

    [DataMember]
    public DateTime EndDatum { get; set; }

    [DataMember]
    public String Beschreibung { get; set; }

    [DataMember]
    [Column("Projektleiter")]
    public Employee Projektleiter { get; set; }

    [DataMember]
    public bool Status { get; set; }

    [DataMember]
    public virtual ICollection<Employee> EmployeesWorkingOnProject { get; set; }

    [DataMember]
    [ForeignKey("Project")]
    public virtual ICollection<ProjectStep> ProjectSteps { get; set; }
}

[DataContract(Namespace = "Shared")]
public class ProjectStep
{
    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public String Beschreibung { get; set; }

    [DataMember]
    public DateTime StartDatum { get; set; }

    [DataMember]
    public DateTime EndDatum { get; set; }

    [DataMember]
    public Project Project { get; set; }
}

并使用Fluent API创建ManyToMany关系以及OneToMany

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

    modelBuilder.Entity<Employee>().HasMany(e => e.Projects).WithMany(t => t.EmployeesWorkingOnProject).Map(m =>
    {
        m.MapLeftKey("MitarbeiterID");
        m.MapRightKey("ProjektID");
        m.ToTable("mitarbeiter_projekte");
    });

    modelBuilder.Entity<ProjectStep>().HasRequired<Project>(p => p.Project).WithMany(p => p.ProjectSteps);
}

我真的很茫然,因为当我尝试插入新的Project时,我收到错误:

  

类型上属性'ProjectSteps'的ForeignKeyAttribute   'Shared.Project'无效。外键名称'Project'不是   在依赖类型'Shared.ProjectStep'上找到。名称值   应该是以逗号分隔的外键属性名称列表。

我认为我的映射中存在一些问题,这是导致此错误的原因。我完全不知道我的映射是错误的,以及我是否使用了正确的方法。

所以我的问题是,如果有人将DataAnnotationsFluent API混合在一起,有人可以帮助我正确制作这张地图吗?

请注意,这是我的第一个C#/ EF6项目,我对所有内容都不太常见,所以欢迎提供一些解释。

2 个答案:

答案 0 :(得分:3)

数据注释和流畅的配置可以混合使用。但特别是对于关系,我发现流畅的配置更加直观。 ForeignKey属性的问题是它可以应用于FK属性,在这种情况下,它用于指定导航属性名称。或者它可以应用于导航属性,在这种情况下,它应该包含FK 属性名称(或复合FK属性名称的逗号分隔列表)。

重要的是要知道不能用于指定FK 名称。列名由Column属性控制,因此只有在您具有明确的FK属性(您不会这样做)时才能使用它。

Fluent API没有这样的限制。您有明确的FK属性时使用HasForeignKey,或者当您没有Map时使用MapKey

在您的情况下,为了指定您不寻常的&#34;项目&#34;作为FK列名称,您可以使用以下流畅的配置(并且不要忘记从ForeignKey中删除无效的ProjectSteps属性):

modelBuilder.Entity<ProjectStep>()
    .HasRequired(p => p.Project)
    .WithMany(s => s.ProjectSteps)
    .Map(m => m.MapKey("Project"));

答案 1 :(得分:1)

为了能够向db添加新的“Project”,您需要从“Project”类中的“ProjectSteps”属性中删除外键注释。 “外键”注释只能应用于非集合类型的属性。

[DataContract(Namespace = "Shared")]
public class Project
{

    public Project()
    {
        this.EmployeesWorkingOnProject = new List<Employee>();
        this.ProjectSteps = new List<ProjectStep>();
    }

    [DataMember]
    [Key]
    public int ID { get; set; }

    [DataMember]
    public String Titel { get; set; }

    [DataMember]
    public DateTime StartDatum { get; set; }

    [DataMember]
    public DateTime EndDatum { get; set; }

    [DataMember]
    public String Beschreibung { get; set; }

    [DataMember]
    [Column("Projektleiter")]
    public Employee Projektleiter { get; set; }

    [DataMember]
    public bool Status { get; set; }

    [DataMember]
    public virtual ICollection<Employee> EmployeesWorkingOnProject { get; set; }

    [DataMember]
    public virtual ICollection<ProjectStep> ProjectSteps { get; set; }
}

在补充中回答你的问题:

  

所以我的问题是,如果有人甚至将DataAnnotations与Fluent API混合在一起,有人可以帮助我正确地进行这种映射吗?

混合不是一个好习惯。 Imho Fluent API总是更好,因为它提供了更多的映射选项。

有关EF映射的详细信息,请查看THIS

相关问题