EF处理带有复合键的一对多模型

时间:2019-04-03 12:00:57

标签: c# entity-framework entity-framework-core

我正在尝试学习.Net Core 2.1,并使用现有数据库测试一个小项目。我们有3个表(Template,TemplateDesc,TemplateParameter),其中之一具有一对多关系。当我获得一个带有控制器的模板时,它为TemplateDescriptions和ParameterValues返回null。另外,如果我尝试删除模板,它将返回FK异常。有人可以指出以下代码的问题吗?

注意:我使用Swagger扩展程序来测试代码。

public class Template
{
    public decimal CompanyCode { get; set; }
    public string TemplateCode { get; set; }
    public List<TemplateDesc> TemplateDescriptions { get; set; }
    public DateTime TemplateDate { get; set; }
    public string RuleCode { get; set; }
    public string SourceTypeCode { get; set; }
    public string Description { get; set; }
    public bool IsBlocked { get; set; }
    public string CreatedUserName { get; set; }
    public DateTime CreatedDate { get; set; }
    public List<TemplateParameter> ParameterValues { get; set; }
}

public class TemplateDesc
{
    public decimal CompanyCode { get; set; }
    public string TemplateCode { get; set; }
    public string LangCode { get; set; }
    public string TemplateDescription { get; set; }
}

public class TemplateParameter
{
    public decimal CompanyCode { get; set; }
    public string TemplateCode { get; set; }
    public string TemplateRuleCode { get; set; }
    public string ParameterName { get; set; }
    public string ParameterValue { get; set; }
}

modelBuilder.Entity<Template>(entity =>
{
    entity.HasKey(e => new { e.CompanyCode, e.TemplateCode });
    entity.HasMany(e => e.TemplateDescriptions).WithOne(e => e.Template).HasForeignKey(e => new { e.CompanyCode, e.TemplateCode });
    entity.HasMany(e => e.ParameterValues).WithOne(e => e.Template).HasForeignKey(e => new { e.CompanyCode, e.TemplateCode });
}

modelBuilder.Entity<TemplateDesc>(entity =>
{
    entity.HasKey(e => new { e.CompanyCode, e.TemplateCode, e.LangCode });
    entity.HasOne(e => e.Template).WithMany(e => e.TemplateDescriptions).HasForeignKey(e => new { e.CompanyCode, e.TemplateCode }).OnDelete(DeleteBehavior.Cascade);
}

modelBuilder.Entity<TemplateParameter>(entity =>
{
    entity.HasKey(e => new { e.CompanyCode, e.TemplateCode, e.TemplateRuleCode, e.ParameterName});
    entity.HasOne(e => e.Template).WithMany(e => e.ParameterValues).HasForeignKey(e => new { e.CompanyCode, e.TemplateCode}).OnDelete(DeleteBehavior.Cascade);
}

[HttpGet]
public ActionResult<Template> GetWithKey([FromQuery] decimal companyCode, [FromQuery] string templateCode)
{
    try
    {
        var template = this.mRepository.Find(e => e.CompanyCode == companyCode && e.TemplateCode.AreEqual(templateCode)).FirstOrDefault();

        if (template == null)
            return new JsonResult(new ApiResponse<Template>(ResponseType.Exception, null));

        return new JsonResult(new ApiResponse<Template>(ResponseType.Success, template));
    }
    catch
    {
        throw;
    }
}

[HttpDelete]
public ActionResult DeleteWithKey([FromQuery] decimal companyCode, [FromQuery] string templateCode)
{
    if (this.mRepository.Find(e => e.CompanyCode == companyCode && e.TemplateCode.AreEqual(templateCode)).Count() < 1)
        return new JsonResult(new ApiResponse<string>(ResponseType.NotFound, templateCode));

    this.mRepository.Delete(companyCode, templateCode);
    return new JsonResult(new ApiResponse<Template>(ResponseType.Success, null));
}

1 个答案:

答案 0 :(得分:0)

您必须使用延迟加载,或使用Include结构:

db.Templates
    .Include(x => x.TemplateDesc)
    .Include(x => x.TemplateParameter)
    .FirstOrDefault(...)

包含项可以放在扩展方法中

public IQueryable<Template> BuildTemplate(this DbSet<Template> set)
{
  return set.Include(x => x.TemplateDesc)
        .Include(x => x.TemplateParameter);
}

然后您就可以使用

dbContext.Templates.BuildTemplate.FirstOrdefault(x => x.TemplateDescriptions.Any(td => td.TemplateCode == "xyz"));