Структура сущности 4.3 с обязательной ассоциацией - PullRequest
4 голосов
/ 16 февраля 2012

Я очень странное поведение с подходом и ассоциациями кода 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 ]

10 голосов
/ 16 февраля 2012

Вот почему вы не должны использовать аннотации данных.Аннотации данных являются неправильной функцией, потому что они выполняют сопоставление и проверку (нарушение единой ответственности) - как вы видите, это не всегда то, что вы хотите.Итак, ваши текущие параметры:

  • Отключить проверку в context.Configuration.ValidateOnSaveEnabled = false
  • Предоставить необнуляемое KpiSectionId свойство внешнего ключа в вашей сущности Region (вам не понадобится Required атрибут вашего свойства навигации).
  • Используйте свободный API вместо аннотаций данных:

Пример:

modelBuilder.Entity<GlobalKpiSection>()
            .WithMany(s => s.Regions)
            .HasRequired(r => r.KpiSection);
2 голосов
/ 16 февраля 2012

Чтобы принудительно удалить каскад, вы должны использовать текущие конфигурации.Затем вы можете удалить атрибут [Required] из свойства KpiSection.

Примерно так:

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 голос
/ 16 февраля 2012

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