Entity Framework Основная проблема навигации без ключа - PullRequest
1 голос
/ 22 января 2020

Я создаю доказательство концепции для моей компании. У нас есть существующая платформа, которую мы будем постепенно заменять современными технологиями. В настоящее время я ограничен использованием наших существующих баз данных, которые имеют несколько таблиц без ключей. Я создаю приложение Blazor WebAssembly, которое вызывает базовое веб-приложение. net с использованием gRP C. Моя проблема в том, что я использую EF Core для связи с существующими базами данных, но я получаю исключение при вызове DbContext.Attach(shipment)

"The navigation '' cannot be added because it targets the keyless entity type 'Document'. Navigations can only target entity types with keys."

Document - это свойство навигации для сущности, Attach редактируемой для DbContext.

Shipment - это очень большая и сложная структура данных, охватывающая многие уровни. Есть ли способ избежать необходимости устанавливать состояние объекта для каждого объекта, DbContext.Entry(entity).State = EntityState.Added, в структуре модели?

Или, возможно, отобразить операции CRUD DbSet на хранимые процедуры?

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

Вот резко сокращенная версия схемы, но это все, что имеет отношение к проблеме.

public class Shipment
{
    public int Id { get; set; }
    // 60 other properties

    public virtual ICollection<Document> Documents { get; set; }
}

public class Document
{
    public int ShippingId { get; set; }
    public string DocumentType { get; set; }
    public byte[] Content { get; set; }

    public virtual Shipment Shipment { get; set; }
}

Когда я пытаюсь прикрепить Shipment сущности на DbContext или вручную установите ее состояние, я получаю исключение выше.

Опять же, я не могу изменить схему базы данных в настоящее время, и есть много других моделей, подобных Document, у которых нет ключа или средства его добавления.

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

Я понимаю, что это требует дальнейшего объяснения. Очевидно, что DbContext не сможет вставить / обновить / удалить, поскольку без ключа он не знает, как это сделать. Все, что мне нужно, это уметь читать при получении сущности Shipping и установке свойства навигации Documents. Но при сохранении Shipping просто полностью игнорируйте свойство навигации.

Ответы [ 2 ]

0 голосов
/ 23 января 2020

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

Я добавил public Guid Id { get; set; } = Guid.NewGuid(); для всех моих ключей без ключа и затем заменил entity.HasNoKey(); на entity.HasAlternateKey(x => x.Id);, используя ModelBuilder. Сводка

HasAlternateKey: создает альтернативный ключ в модели для этого типа сущности, если он не существует над указанными свойствами. Это заставит свойства быть доступными только для чтения.

Это именно то, что я искал.

0 голосов
/ 23 января 2020

Если этот класс Document отражает полную схему для таблицы документов, то вы не можете и, вероятно, не должны пытаться связать документы с помощью свойств навигации EF. Хотя схема может прекрасно работать с односторонними отношениями из таблицы, в которой нет PK, EF не может управлять отношениями таким образом. Как именно вы можете отличить один документ от другого? В действительности система может и не понадобиться, но как ORM, предназначенная для надежной загрузки и управления данными, это требование.

Обычно, когда в таблице нет PK, вы можете удовлетворить EF, определив предоставленный ключ Есть достаточно полей, чтобы однозначно дифференцировать записи. Например ShippingId + CreatedAt и, возможно, CreatedBy, если необходимо. Однако в вашей обрисованной схеме есть только двоичное содержимое, которое не может служить частью ключа.

Если вы не можете настроить схему так, чтобы ввести бессмысленный ключ (все таблицы должны иметь PK), то я бы сказал, что ваш единственный вариант - удалить связь с EF и загрузить документы отгрузкой полностью отдельно. , Из-за потенциально больших двоичных данных, которые используются редко, наличие навигационных свойств может быть потенциально опасным, например, попытка Include их или непредвиденное отключение их ленивого загрузочного прокси-сервера чем-то вроде сериализатора может парализовать систему.

...