我目前正在开发一个应该将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'上找到。名称值 应该是以逗号分隔的外键属性名称列表。
我认为我的映射中存在一些问题,这是导致此错误的原因。我完全不知道我的映射是错误的,以及我是否使用了正确的方法。
所以我的问题是,如果有人将DataAnnotations
与Fluent API
混合在一起,有人可以帮助我正确制作这张地图吗?
请注意,这是我的第一个C#/ EF6项目,我对所有内容都不太常见,所以欢迎提供一些解释。
答案 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