我目前正在开发一个项目(WCF 服务),该项目应将 EF6 与 MySql 数据库结合使用。该部分本身已经可以正常工作,但是我在映射方面遇到了很大的问题。
我有如下 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`)
)
项目步骤表:
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
时,我得到了错误:
The ForeignKeyAttribute on property 'ProjectSteps' on type 'Shared.Project' is not valid. The foreign key name 'Project' was not found on the dependent type 'Shared.ProjectStep'. The Name value should be a comma separated list of foreign key property names.
我认为我的映射存在一些问题,这是导致此错误的原因。我完全不知道我的映射在哪里出错,甚至不知道我是否使用了正确的方法。
所以我的问题是,是否应该将 DataAnnotations
与 Fluent API
混合使用,有人可以帮助我正确设置此映射吗?
请注意,这是我的第一个 C#/EF6 项目,我对所有事情都不太熟悉,因此欢迎提供一些解释。
最佳答案
数据注释和流畅的配置可以混合使用。但特别是对于关系,我发现流畅的配置更加直观。 ForeignKey
的问题attribute 是它可以应用于 FK 属性,在这种情况下它用于指定导航属性名称。或者它可以应用于导航属性,在这种情况下它应该包含 FK 属性 名称(或复合 FK 属性名称的逗号分隔列表)。
要知道的重要一点是,它不能用于指定 FK 列 名称。列名由 Column
控制属性,因此只有当您具有明确的 FK 属性(您没有)时才能使用它。
Fluent API 没有这样的限制。您要么使用 HasForeignKey
当你有明确的 FK 属性时,或 Map
与 MapKey
当你不这样做时。
在您的情况下,为了将不寻常的“项目”指定为 FK 列名称,您可以使用以下流畅的配置(并且不要忘记从 ForeignKey
中删除无效的 ProjectSteps
属性):
modelBuilder.Entity<ProjectStep>()
.HasRequired(p => p.Project)
.WithMany(s => s.ProjectSteps)
.Map(m => m.MapKey("Project"));
关于C# EF6 实体映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49590830/