我当前正在研究一个项目(WCF服务(,该项目应使用MySQL数据库使用EF6。那部分本身已经在工作应有的,但是我在映射方面遇到了巨大的问题。
我有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`)
)
映射表员工 - 项目
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"上的外国基归因于 "共享"项目无效。外国关键名称"项目"不是 在依赖类型的"共享.projectStep"上找到。名称值 应该是外国关键属性名称的逗号分开列表。
我认为我的映射有一些问题,这是造成此错误的原因。对于我的映射是错误的,以及我什至使用正确的方式,我完全不知所措。
所以我的问题是,是否应该将DataAnnotations
与Fluent API
混合,有人可以帮助我正确地映射吗?
请注意,这是我的第一个C#/EF6项目,我对所有内容都不是很常见,因此欢迎一些解释。
可以混合使用数据注释和流利的配置。但是尤其是对于关系,我发现流利的配置更加直观。ForeignKey
属性的问题在于它可以应用于FK属性,在这种情况下,它用于指定导航属性名称。或可以将其应用于导航属性,在这种情况下,它应包含FK 属性名称(或Comma分离的复合FK属性名称列表(。
要知道的重要一件事是,它不能使用不能用来指定FK 列名称。列名由Column
属性控制,因此仅在您具有显式fk属性时才可以使用。
流利的API没有这种局限性。当您具有明确的FK属性时,您要么使用HasForeignKey
,要么在不使用MapKey
时使用CC_11。
在您的情况下,为了将您的异常"项目"指定为FK列名称,您可以使用以下流利的配置(并且不要忘记从ProjectSteps
删除无效的ForeignKey
属性(:
modelBuilder.Entity<ProjectStep>()
.HasRequired(p => p.Project)
.WithMany(s => s.ProjectSteps)
.Map(m => m.MapKey("Project"));
为了能够将新"项目"添加到db,您需要从"项目"类中的" 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; }
}
在添加的问题中回答您的问题:
所以我的问题是,是否应该将数据通道与流利的API混合在一起,有人可以帮助我正确地映射吗?
混合不是一个好习惯。恕我直言流利的API总是更好,因为它提供了更多的映射选项。
有关EF映射的更多信息,请查看此