Entity Framework 4.3中的必需关联

5

我是一个使用EF Code First方法和关联的非常奇怪的行为。我有两个实体:

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属性上添加required属性。

问题在于以下代码:

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

我遇到了一个异常问题,提示必需的字段未初始化,但该字段已经存在,只是没有加载。当我使用此实体时,我不想为属性处处显式包含代码。有什么方法可以解决这个问题呢?异常详情

更新

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

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

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

你是否使用配置类来建模一对多的关系? - Jayanga
不,它是按照约定映射的。 - Sly
我认为在Fluent API中使用配置类会是一个不错的解决方案。 - Jayanga
3个回答

11

因此,您不应使用数据注释。数据注释是错误的特性,因为它们既进行映射又进行验证(违反单一职责)-正如您所看到的,并不总是您想要的。因此,您当前的选项为:

  • context.Configuration.ValidateOnSaveEnabled = false中关闭验证
  • 在您的Region实体中公开非空的KpiSectionId外键属性(您将不需要导航属性上的Required属性)。
  • 使用流畅的API而不是数据注释:

例如:

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

1
他们既进行映射又进行验证(违反单一职责原则)。好的,你最终说服我放弃数据注释,转而使用流畅的API。谢谢。 - Carl G

3

要强制级联删除,您需要使用流畅的配置。然后可以从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());
    }
}

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接