简体   繁体   English

C#EF6实体映射

[英]C# EF6 entity mapping

I am currently working on a project (WCF Service) that should utilize EF6 with a MySql database. 我目前正在开发一个项目(WCF服务),该项目应将EF6与MySql数据库一起使用。 That part itself is already working as it should, but I am having huge problems with the mapping. 该部分本身已经可以正常工作,但是映射存在很大问题。

I have 3 entities like following: 我有3个实体,如下所示:

Employee - ManyToMany - Project - OneToMany - ProjectStep

My database model is set up like this: 我的数据库模型是这样建立的:

Employee table: 员工表:

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`)
)

Project table: 项目表:

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 table: 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`)
)

Mapping table 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`)
)

I then created my entities as following: 然后,我按如下方式创建我的实体:

[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; }
}

and used Fluent API to create the ManyToMany relationship as well as the OneToMany : 并使用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);
}

I am really at a loss, because when I am trying to insert a new Project , I get the error: 我真的很茫然,因为当我尝试插入一个新的Project ,出现错误:

The ForeignKeyAttribute on property 'ProjectSteps' on type 'Shared.Project' is not valid. 类型'Shared.Project'上属性'ProjectSteps'上的ForeignKeyAttribute无效。 The foreign key name 'Project' was not found on the dependent type 'Shared.ProjectStep'. 在从属类型“ Shared.ProjectStep”上找不到外键名称“ Project”。 The Name value should be a comma separated list of foreign key property names. Name值应该是逗号分隔的外键属性名称列表。

I think that I have a few problems in my mapping which are the reason for this error. 我认为映射中存在一些问题,这是导致此错误的原因。 I am completely at a loss as to where my mapping is wrong as well as if I even used the right way. 对于我的映射错误以及我什至使用了正确的方法,我完全是茫然。

So my question is, should one even mix the DataAnnotations with Fluent API , and could someone help me getting this mapping right? 因此,我的问题是,是否应该将DataAnnotationsFluent API混合使用,有人可以帮助我正确实现此映射吗?

Please note, that this is my very first C#/EF6 project and that I am not very common with everything so some explanation is welcome. 请注意,这是我的第一个C#/ EF6项目,我在所有方面都不是很普通,因此欢迎您进行一些解释。

Data annotations and fluent configurations can be mixed. 数据注释和流利的配置可以混合使用。 But especially for relationships I find fluent configuration much more intuitive. 但是特别是对于关系,我发现流畅的配置更加直观。 The problem with ForeignKey attribute is that it could be applied to the FK property, in which case it is used to specify the navigation property name. ForeignKey属性的问题在于它可以应用于FK属性,在这种情况下,它用于指定导航属性名称。 Or it could be applied to the navigation property, in which case it should contain the FK property name (or comma separated list of composite FK property names). 或者可以将其应用于导航属性,在这种情况下,它应包含FK 属性名称(或复合FK属性名称的逗号分隔列表)。

The important thing to know is that it cannot be used to specify the FK column name. 要知道的重要一点是,它不能用于指定FK 名称。 The column names are controlled by the Column attribute, hence it can be used only if you have explicit FK property (which you don't). 列名由Column属性控制,因此仅当您具有显式FK属性(您没有)时才可以使用它。

Fluent API has no such limitations. Fluent API没有这样的限制。 You either use HasForeignKey when you have explicit FK property, or Map with MapKey when you don't. 你要么使用HasForeignKey当你有明确的FK财产,或MapMapKey ,当你不知道。

In your case, in order to specify your unusual "Project" as FK column name, you can use the following fluent configuration (and don't forget to remove the invalid ForeignKey attribute from ProjectSteps ): 在您的情况下,为了将您不寻常的“ Project”指定为FK列名,您可以使用以下流畅的配置(并且不要忘记从ProjectSteps删除无效的ForeignKey属性):

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

In order to be able to add new "Project" to db, you'll need to remove foreign key annotation from "ProjectSteps" property in "Project" class. 为了能够向数据库添加新的“ Project”,您需要从“ Project”类的“ ProjectSteps”属性中删除外键注释。 "Foreign Key" annotation can be applied only to properties which are not collection type. “外键”注释只能应用于不是集合类型的属性。

[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; }
}

In addtition answering you question: 另外回答您的问题:

So my question is, should one even mix the DataAnnotations with Fluent API, and could someone help me getting this mapping right? 所以我的问题是,是否应该将DataAnnotations与Fluent API混合使用,有人可以帮助我正确实现此映射吗?

Mixing is not a good practice. 混合不是一个好习惯。 Imho Fluent API is always better, because it gives much more mapping options. Imho Fluent API总是更好,因为它提供了更多的映射选项。

For more info about EF mappings, check out THIS 有关EF映射的更多信息,请查看THIS

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM