EF Fluent API - 检索相关实体

时间:2017-10-05 23:40:32

标签: mysql .net entity-framework ef-fluent-api

我有项目类,每个项目都有WorkOrders。 这些是在MySQL中创建的表

CREATE TABLE `project` (
    `idProject` INT(11) NOT NULL AUTO_INCREMENT,
    `idCompany` INT(11) NOT NULL,
    `Title` VARCHAR(100) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
    PRIMARY KEY (`idProject`, `idCompany`),
    INDEX `FK_project_company` (`idCompany`),
    CONSTRAINT `FK_project_company` FOREIGN KEY (`idCompany`) REFERENCES `company` (`idCompany`) ON UPDATE NO ACTION ON DELETE NO ACTION
)
;

CREATE TABLE `project_workorders` (
    `idProjectWO` INT(11) NOT NULL AUTO_INCREMENT,
    `idProject` INT(11) NOT NULL DEFAULT '0',
    `idWorkOrder` INT(11) NOT NULL DEFAULT '0',
    PRIMARY KEY (`idProjectWO`, `idProject`, `idWorkOrder`),
    INDEX `FK_project_workorders_project` (`idProject`),
    INDEX `FK_project_workorders_workorder` (`idWorkOrder`),
    CONSTRAINT `FK_project_workorders_project` FOREIGN KEY (`idProject`) REFERENCES `project` (`idProject`) ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT `FK_project_workorders_workorder` FOREIGN KEY (`idWorkOrder`) REFERENCES `workorder` (`idWorkOrder`) ON UPDATE NO ACTION ON DELETE NO ACTION
);

然后有FluentAPI配置文件

class ProjectConfiguration : EntityTypeConfiguration<Project>
    {
        internal ProjectConfiguration()
        {
            this.HasKey(p => new { p.idProject , p.idCompany});
            this.Property(p => p.idProject)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.HasRequired<MaxUser>(p => p.CreatedByUser)
                .WithMany()
                .HasForeignKey(p => p.CreatedByID);
            this.HasMany(s => s.ProjectWO)
                .WithRequired(w=>w.Project)
                .HasForeignKey(k=>new { k.idProject,k.idProjectWO});
            this.Map(m =>
            {
                m.MapInheritedProperties();
            });
        }
    }

    class ProjectWOConfiguration : EntityTypeConfiguration<ProjectWO>
    {
        internal ProjectWOConfiguration()
        {
            this.HasKey(p=> new { p.idProjectWO , p.idProject, p.idWorkOrder });
            this.Property(p => p.idProjectWO)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            this.HasRequired<MaxUser>(p => p.CreatedByUser)
                .WithMany()
                .HasForeignKey(p => p.CreatedByID);
            this.Map(m =>
            {
                m.MapInheritedProperties();
            });
        }
    }

问题是我无法让相关实体出现在Project对象中。 无论我尝试什么,ProjectWO子对象总是空的。

enter image description here

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

关于MapKey ......这与EF 6有关,看来EF Core没有这个功能,所以我不太清楚如何定义没有FK属性的关系。 (因此,为什么我倾向于避免前沿技术,直到其他人都变得血腥,并且对作者尖叫以使其可用。)

鉴于以下实体:

public class Project
{
   public int IdProject { get; set; }
   public virtual List<ProjectWorkOrder> WorkOrders { get; set; }
   ...
}

public class ProjectWorkOrder
{
   public int IdProjectWO { get; set; }
   public virtual Project { get; set; }
   public virtual WorkOrder {get; set; }
   ...
}

public class WorkOrder
{ 
   public int IdWorkOrder { get; set; }
   public virtual List<ProjectWorkOrder> Projects { get; set; }
   ...
}

MapKey将进入Project实体配置:

public class ProjectConfiguration : EntityTypeConfiguration<Project>
{
   public ProjectConfiguration()
   {
      ToTable("projects");
      HasKey(x => x.IdProject)
         .Property( x => x.IdProject)
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

      .HasMany(x => x.WorkOrders)
         .WithRequired(x => x.Project)
         .Map(x => x.MapKey("idProject")
         .WillCascadeOnDelete(true);


public class ProjectWorkOrderConfiguration : EntityTypeConfiguration<ProjectWorkOrder>
{
   public ProjectWorkOrderConfiguration()
   {
      ToTable("project_workorders");
      HasKey(x=> x.IdProjectWO)
      Property(x => x.idProjectWO)
         .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

      HasRequired(x => x.Project)
         .WithMany(x => x.WorkOrders)
         .WillCascadeOnDelete(false);
      HasRequired(x => x.WorkOrder)
         .WithMany(x => x.Projects)
         .WillCascadeOnDelete(false);
   }
}

通过告诉EF关于FK列,您无需在实体中声明FK值。对于实体,我建议使用引用成员(即ProjectWorkOrder中的Project引用)或FK字段,或者两者都不使用;但不是参考和FK。这样做的原因是,当你同时拥有引用和FK时,这可能会导致代码和EF中的混淆,此时需要将更改保存到实体。如果我设置对ID为1的实体实例的引用,但是然后可以将FK字段设置为“2”,那么我相信EF会做什么?通常,为了避免这种奇怪,您需要向setter添加代码,以确保永远不能将引用和FK设置为​​不同的值。因此,如果您正在使用EF Core,那么这可能是您需要考虑的路线,除非有人知道如何获得.HasForeignKey等来处理架构而不是实体。

我是否将引用添加回父母将取决于哪些实体在我的系统中作为顶级。例如,如果我总是处理项目并且想要获得相关的工作订单而不需要从工作订单返回到项目,那么我的ProjectWorkOrder实体就不会打扰项目或ProjectId,Project只会注册一个。 HasMany(x =&gt; x.WorkOrders).Map(x =&gt; x.MapKey(“idProject”)。WithRequired();如果我从WorkOrder转到项目,那么我将拥有导航属性。在某些情况下我不关心实体细节,只关联(即查找)然后在那些情况下我只是映射FK。通常这些将链接到枚举或名称 - 值对。这个例子假设2-导航方式。