#c# #entity-framework
#c# #entity-framework
Вопрос:
У меня есть что-то вроде следующего:
public class EntityA
{
[Required]
long? EntityBId { get; set; }
[ForeignKey("EntityBId ")]
public virtual EntityB { get; set; }
}
public class EntityB
{
[Key]
long EntityBId { get; set; }
}
Когда я использую его следующим образом, я получаю ошибку проверки, потому что требуемое свойство EntityBId
равно null.
EntityA a = new EntityA();
a.EntityB = new EntityB();
dbContext.EntityAs.Add(EntityA);
dbContext.SaveChanges();
Однако, если я удалю [Required]
атрибут, то оба EntityA
и EntityB
будут добавлены в базу данных и EntityBId
будут заполнены SaveChanges
вызовом.
Как я могу пометить EntityBId
как [Required]
и избежать сбоя проверки entity framework?
Комментарии:
1. Зачем вам нужно пометить его как
[Required]
, если вам не нужно, чтобы он был обязательным?2. @Alexander это обязательно
Ответ №1:
Смотрите эту ссылку для использования требуемой аннотации:https://learn.microsoft.com/en-us/ef/ef6/modeling/code-first/data-annotations —
«Требуемая аннотация сообщает EF, что требуется определенное свойство.
Добавление Required к свойству Title заставит EF (и MVC) убедиться, что в этом свойстве есть данные.»
итак, вам нужно решить, хотите ли вы аннотацию [Required], тогда это означает, что она не разрешит свойство с нулевым значением. И если вас устраивает значение null, удалите аннотацию [Обязательно].
Комментарии:
1. Свойство не должно быть нулевым. Это идентификатор требуемого связанного объекта. Связь устанавливается путем присвоения экземпляра виртуальному свойству для связанного объекта. Затем entity Framework заполняет идентификатор на своей стороне во время вызова SaveChanges. Что и происходит, если ему передается его собственная проверка.
2. если вы измените его с nullable<long>(длинный?) для параметра long по умолчанию будет установлено значение 0, а EF автоматически присвоит правильный идентификатор при сохранении.
3. Возможно, не уверен, обеспечит ли это желаемое поведение. Мне придется протестировать. Проблема может заключаться в том, что 0 является допустимым значением, указывающим на отдельную запись. Я не уверен, как entity Framework узнает, поддерживается ли указывать на запись 0 или присваивать значение из вставляемой новой записи.
4. @denver — Когда вы установите свойство навигации (виртуальное свойство) в значение instance EF правильно установит foreign key в идентификатор, созданный для указанной записи. Попробуйте.
5. Проверял, согласно моему последнему комментарию, если вы установили идентификатор равным 0, у entity framework возникает проблема и выдается исключение. Это меня не удивляет, потому что entity framework поставляется с противоречивой информацией. Я предполагаю, потому что внешний ключ имеет идентификатор, подразумевающий, что он уже есть в базе данных, в то время как экземпляр свойства навигации (virtual property) не является и не имеет идентификатора.
Ответ №2:
Может быть два сценария:
Первый: EntityB
уже существующий в базе данных, и вы указываете EntityBId
из EntityB
на EntityBId
ForeignKey
из нового EntityA
следующим образом, и в этом случае только EntityA
будет вставлен в базу данных:
EntityB entityB = dbContext.EntityBs.FirstOrDefault(yourCondition)
EntityA entityA = new EntityA();
entityA.EntityBId = entityB.EntityBId; // <-- assign `ForeignKey` value instead of navigation property value, hence no required validation error will occur
dbContext.EntityAs.Add(entityA);
dbContext.SaveChanges();
Second: EntityB
еще не существует в базе данных, и он будет заново вставлен в базу данных вместе с EntityA
. Итак, в этом случае ваш код должен быть следующим:
EntityB entityB = new EntityB();
dbContext.EntityBs.Add(entityB);
EntityA entityA = new EntityA();
entityA.EntityBId = entityB.EntityBId; // <-- assign `ForeignKey` value instead of navigation property value, hence no required validation error will occur
dbContext.EntityAs.Add(entityA);
dbContext.SaveChanges();
Теперь решите, каков ваш сценарий, и действуйте соответственно.
Комментарии:
1. Вторая ситуация в игре. Предоставленный вами код не будет работать, поскольку EntityB.EntityBId имеет значение null до вызова SaveChanges.
2. @denver
The code you provide will not work because entityB.EntityBId is null
— Нет! это сработает. EF достаточно умен, чтобы поддерживать это во время вставки.3. Попробуйте свой код. Вы устанавливаете EntityA.EntityBId = null (эта строка ничего не делает). Затем проверка завершится неудачей, поскольку EntityBId помечен как обязательный. Если EntityBId не был отмечен, required entity framework установит связь во время вставки.
4. @denver не
EntityBId
является автоматически увеличиваемым первичным ключом?5. EntityBId — это первичный ключ, я полагаю, что по умолчанию он автоматически увеличивается.