2

У меня есть база данных с большим количеством отношений. К сожалению, это старая поддерживаемая база данных, которая, похоже, не понимает концепцию ассоциации или ключей, которой иногда не хватает. Это основное использование в другом приложении, поэтому я больше не хочу менять базу данных (но скорее настраиваю Entity Framework)Использовать внешние ключи в качестве первичного ключа

Проблема, которую я имею, заключается в попытке использовать внешние ключи в качестве первичных ключей, как (я думаю) используй это.

Мои таблицы называются

Operation{ Criteria { Parameter{ CriteriaSelection { 
    ID   ID,   ID,   ID, 
    ..   ..   ..   .. 
}    }    }    } 

CheckpointOperation { 
    ID, 
    Criteria_ID, 
    .. 
} 

CheckpointParameter { 
    // missing primary key 
    CheckpointOperation_ID, // a CheckpointOperation has many CheckpointParameters 
    CriteriaSelection_ID, // a CheckpointParameter has one CriteriaSelection 
    Parameter_ID,   // .. and one Parameter 
    .. 
} 

Проблема здесь в том, что CheckpointParameter не имеет первичный ключ, определенный конкретно, а первичный ключ { CheckpointOperation_ID, CriteriaSelection_ID, Parameter_ID }. Теперь я пытаюсь сопоставить это в EntityFramework с class CheckpointParameterMap : EntityTypeConfiguration<CheckpointParameter>.

public class CheckpointOperation 
{ 
    public int Id { get; set; } 
    public virtual Operation Operation { get; set; } 

    public virtual ICollection<CheckpointParameter> Parameters { get; set; } 
} 

public class CheckpointParameter 
{ 
    public int OperationId { get; set; } 

    public virtual CheckpointOperation CheckpointOperation { get; set; } 
    public virtual CriteriaSelection Criteria { get; set; } 
    public virtual QualityParameter Parameter { get; set; } 
} 

public class CheckpointParameterMap : EntityTypeConfiguration<CheckpointParameter> 
{ 
    public CheckpointParameterMap() 
    { 
     HasKey(p => new { p.OperationId }); 

     Property(p => p.OperationId) 
      .HasColumnName("CheckpointOperation_ID"); 

     HasRequired(p => p.CriteriaSelection) 
      .WithRequiredDependent() 
      .Map(map => map.MapKey("CriteriaSelection_ID")); 

     HasRequired(p => p.Parameter) 
      .WithRequiredDependent() 
      .Map(map => map.MapKey("Parameter_ID")); 

     HasRequired(p => p.CheckpointOperation) 
      .WithMany(o => o.CheckpointParameters) 
      .HasForeignKey(p => p.OperationId); 
    } 
} 

Но это дает мне ошибку, как из

Multiplicity is not valid in Role 'CheckpointParameter_CheckpointOperation_Source' in relationship 'CheckpointParameter_CheckpointOperation'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be '1'.\r\n"}

Так что я попытался удалить HasKey, но это дает мне ошибку

EntityType 'CheckpointParameter' has no key defined. Define the key for this EntityType.\r\n\tSystem.Data.Entity.Edm.EdmEntitySet: EntityType: EntitySet 'CheckpointParameters' is based on type 'CheckpointParameter' that has no keys defined.\r\n"}

Затем я попытался использовать иностранные критерии, а также первичный ключ, так как у меня есть название столбца:

public class CheckpointParameter 
{ 
    ... 
    public int CriteriaSelectionId { get; set; } 
    ... 
} 

public CheckpointParameterMap() 
{ 
    HasKey(p => new { p.OperationId, p.CriteriaSelectionId }); 
    //... 
    Property(checkpointParameter => checkpointParameter.CriteriaSelectionId) 
     .HasColumnName("CEC_ID"); 
} 

Но это дает мне следующую ошибку:

{"Schema specified is not valid. Errors: \r\n(48,6) : error 0019: Each property name in a type must be unique. Property name 'CriteriaSelection_ID' was already defined."}

Что такое правильный способ определения первичного ключа, которые являются внешними ключами, без изменения базы данных?

+0

Вы побегать отдельный запрос по этим столбцам в копии производственных данных? Похоже, вы уверены, что сочетание этих ключей образует естественный ключ таблицы. Если это так, то вперед и создайте первичный ключ SQL для этих столбцов. –

+0

У меня есть копия производственных данных, да. У меня есть доступ к базе данных Oracle, где определены таблицы, которые содержат следующее (что для меня подтверждает, что это ключ): 'CREATE UNIQUE INDEX" X "." I $ CEPOQ $ UNIQUE "ON" X "." CEPOQ "(" CEC_ID "," CEPO_ID "," Q_ID "," FRQ ")', где cec - это критерии, cepo - Ch.Operation, а q - параметр. Пожалуйста, поправьте меня, если я ошибаюсь – Default

+0

В этом ответе http://stackoverflow.com/a/15704189/2516770 указано, что Oracle не считает уникальный индекс также уникальным ограничением или ключевым ограничением. Исходя из первого сообщения об ошибке, я предполагаю, что создание уникального ограничения ключа скажет поставщику Oracle EF, что он имеет дело с отдельным значением для 1 стороны отношения (1: n). Однако это всего лишь предположение. –

ответ

1

Вам нужно в критериях Mapping и операции добавить, что поле будет ссылка, как это:

this.HasKey(x => x.OperationId); // In Operation Mapping 

this.HasKey(x => x.CriteriaId); // In Criteria Mapping 

И в критериях или операции вы должны сопоставить некоторые, как это:

this.HasMany(b => b.Criterias) 
    .WithMany(x=> x.Operations) 
    .Map(x => 
    { 
     x.ToTable("CheckpointParameter"); 
     x.MapLeftKey("CriteriaId"); 
     x.MapRightKey("OperationId"); 
    }); 
+0

hm .. Но их не так много, не так ли? Я имею в виду, что «CheckpointOperation» имеет много контрольных точек. «CheckpointParameter» имеет знание ** одного ** «CriteriaSelection» и ** one ** 'Parameter'. Не могли бы вы объяснить, почему я должен использовать «WithMany»? – Default

+0

Не могли бы вы объяснить модели с диаграммой классов? – Santin

+0

Я сделал некоторую дальнейшую отладку, и мне кажется, мне действительно нужно использовать 'WithMany', как вы предложили. Я также заметил, что использование 'HasForeignKey' работало лучше, чем' Map', так как (я думаю), ему не нужно загружать другой столбец, а просто свойство внешнего ключа. – Default

Смежные вопросы