具有必需关联的实体框架4.3

时间:2012-02-16 11:06:58

标签: entity-framework validation lazy-loading code-first

我是EF代码第一种方法和关联的一种非常奇怪的行为。我有两个实体:

public class GlobalKpiSectionn
{
    public GlobalKpiSection()
    {
        this.Regions = new HashSet<Region>();
    }

    public virtual ICollection<Region> Regions { get; protected set; }  
}

public class Region
{
    public int RegionId { get; set; }

    public bool IsMain { get; set; }

    [Required]
    public virtual GlobalKpiSection KpiSection { get; set; }
}

我需要KiSection属性的必需属性才能获得级联删除。

问题如下 - 在此代码中:

var mainRegion = context.Regions.Single(x => x.RegionId == id);
mainRegion.IsMain = true;
context.SaveChanges();

我遇到异常,即必填字段未初始化。但 目前尚未加载。当我使用这个实体时,我不会写任何明确包含属性的内容。我该怎么做才能克服这个问题? Exceptoin details

更新

我确定其延迟加载问题的原因是:

        var primaryRegion = context.Regions
                                   .Include(x => x.KpiSection)
                                   .Single(x => x.RegionId == id);

解决了这个问题,但它绝对是一个糟糕的解决方案。

3 个答案:

答案 0 :(得分:10)

这就是为什么你不应该使用数据注释。数据注释是错误的功能,因为它们同时进行映射和验证(违反单一责任) - 正如您所看到的那样并不总是您想要的。所以你目前的选择是:

  • 关闭context.Configuration.ValidateOnSaveEnabled = false
  • 中的验证
  • 在您的KpiSectionId实体中展示不可为空的Region外键属性(您的导航属性不需要Required属性)。
  • 使用流畅的API代替数据注释:

示例:

modelBuilder.Entity<GlobalKpiSection>()
            .WithMany(s => s.Regions)
            .HasRequired(r => r.KpiSection);

答案 1 :(得分:2)

要强制级联删除,您必须使用流畅的配置。然后,您可以从KpiSection属性中删除[Required]属性。

这样的事情:

public class GlobalKpiSectionn
{
    public GlobalKpiSection()
    {
        this.Regions = new HashSet<Region>();
    }

    public virtual ICollection<Region> Regions { get; protected set; }  
}

public class Region
{
    public int RegionId { get; set; }

    public bool IsMain { get; set; }

    public int GlobalKpiSectionId { get; set; }
    public virtual GlobalKpiSection KpiSection { get; set; }
}

public class RegionConfig : EntityTypeConfiguration<Region>
{
    HasRequired(x => x.KpiSection)
        .WithMany(x => x.Regions)
        .HasForeignKey(x => x.GlobalKpiSectionId)
        .WillCascadeOnDelete(true);
}

public class YourContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new RegionConfig());
    }
}

答案 2 :(得分:1)

EF验证实体时禁用了延迟加载。这样做是为了避免由于对导航属性进行验证而导致不必要的数据库往返。

为实体中的标量属性建模并将验证属性放在那里。

public class Region
{
    public int RegionId { get; set; }

    public bool IsMain { get; set; }

    [Required]
    public int? KpiSectionId { get; set; }

    public virtual GlobalKpiSection KpiSection { get; set; }
}