Невозможно отправить сообщение с KafkaNull в качестве значения

Коллекции: Это не имеет значения.

Существует отличная разница между коллекциями и ссылками в качестве свойств навигации. Ссылка - объект. Коллекции содержат объекты . Это означает, что инициализация коллекции бессмысленна с точки зрения бизнес-логики: она не определяет связь между сущностями. Установка ссылки делает.

Итак, это исключительно вопрос предпочтения, независимо от того, вы или нет инициализируете встроенные списки.

Что касается «как», некоторые люди предпочитают ленивую инициализацию :

private ICollection<Address> _addresses;

public virtual ICollection<Address> Addresses
{ 
    get { return this._addresses ?? (this._addresses = new HashSet<Address>());
}

Он предотвращает ненужные ссылочные исключения, поэтому он облегчает модульное тестирование и управление сборкой, но также предотвращает ненужную инициализацию. Последнее может иметь значение, когда класс имеет относительно много коллекций. Недостатком является то, что требуется относительно много сантехники, особенно. по сравнению с авто свойствами без инициализации. Кроме того, появление оператора null-распространения в C # сделало менее актуальным инициализацию свойств коллекции.

... если не применена явная загрузка

Единственное, что инициализация коллекции затрудняют проверку того, была ли коллекция загружена Entity Framework. Если коллекция инициализирована, такой оператор, как ...

var users = context.Users.ToList();

... создаст объекты User, имеющие пустые, а не нулевые Addresses коллекции (отложенная загрузка). Для проверки того, загружена ли сборка, необходим код, например ...

var user = users.First();
var isLoaded = context.Entry(user).Collection(c => c.Addresses).IsLoaded;

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

if (/*check collection isn't loaded*/)
    context.Entry(user).Collection(c => c.Addresses).Load();

... может быть удобнее не инициализировать свойства коллекции.

Ссылка свойства: Не

Справочные свойства являются объектами, поэтому назначение пустого объекта для них имеет смысл.

Хуже того, если вы инициируете их в конструкторе, EF не будет перезаписывать их при материализации вашего объекта или ленивой загрузкой. Они всегда будут иметь свои начальные значения, пока вы активно не замените их. Хуже того, вы даже можете сохранить пустые объекты в базе данных!

И есть еще один эффект: fixup не будет возникать. Фиксация связей - это процесс, посредством которого EF соединяет все объекты в контексте с помощью своих свойств навигации. Когда User и Licence загружаются отдельно, все еще User.License будет заполняться и наоборот. Если, конечно, если License не был инициализирован в конструкторе. Это справедливо и для 1: n ассоциаций. Если Address инициализирует User в своем конструкторе, User.Addresses не будет заполнен!

Ядро Entity Framework

Фиксация связей в ядре Entity Framework (2.1 в то время записи) не влияет на инициализированные свойства ссылочной навигации в конструкторах. То есть, когда пользователи и адреса извлекаются из базы данных отдельно, свойства навигации заполняются. Однако ленивая загрузка делает не перезаписывать инициализированные свойства ссылочной навигации. Итак, в заключении, а также в EF-ядро инициализирует ссылки навигационных свойств в конструкторах могут вызвать проблемы. Не делай этого. Это не имеет никакого смысла,

0
задан S. Harwood 18 January 2019 в 16:14
поделиться

1 ответ

Я открыл для этого проблему GitHub .

РЕДАКТИРОВАТЬ

Обходной путь - это работает ...

@SpringBootApplication
@EnableBinding(Source.class)
public class So54257687Application {

    public static void main(String[] args) {
        SpringApplication.run(So54257687Application.class, args);
    }

    @Bean
    public ApplicationRunner runner(MessageChannel output) {
        return args -> output.send(new GenericMessage<>(KafkaNull.INSTANCE));
    }

    @KafkaListener(id = "foo", topics = "output")
    public void listen(@Payload(required = false) byte[] in) {
        System.out.println(in);
    }

    @Bean
    @StreamMessageConverter
    public MessageConverter kafkaNullConverter() {
        class KafkaNullConverter extends AbstractMessageConverter {

            KafkaNullConverter() {
                super(Collections.emptyList());
            }

            @Override
            protected boolean supports(Class<?> clazz) {
                return KafkaNull.class.equals(clazz);
            }

            @Override
            protected Object convertFromInternal(Message<?> message, Class<?> targetClass, Object conversionHint) {
                return message.getPayload();
            }

            @Override
            protected Object convertToInternal(Object payload, MessageHeaders headers, Object conversionHint) {
                return payload;
            }

        }
        return new KafkaNullConverter();
    }

}
0
ответ дан Gary Russell 18 January 2019 в 16:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: