Зачем добавлять свойство внешнего ключа для объектов в EF [дубликат]

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

Случай с краем # 1: одновременный доступ к словарю

Родовые словари в .NET не являются потокобезопасными, а иногда могут бросать NullReference или даже (чаще) a KeyNotFoundException при попытке получить доступ к ключу из двух параллельных потоков. Исключение в этом случае является довольно ошибочным.

Случай с краем # 2: небезопасный код

Если код NullReferenceException задан кодом unsafe, вы можете посмотреть на переменные указателя , и проверьте их на IntPtr.Zero или что-то в этом роде. Это одно и то же («исключение нулевого указателя»), но в небезопасном коде переменные часто переводятся в типы значений / массивы и т. Д., И вы ударяете головой о стену, задаваясь вопросом, как тип значения может исключение.

(Еще одна причина для небезопасного использования небезопасного кода, если вам это нужно)

98
задан Daniel Liuzzi 12 March 2011 в 14:13
поделиться

4 ответа

Если вы хотите в полной мере использовать ORM, вы обязательно будете использовать ссылку Entity:

public class Order
{
    public int ID { get; set; }
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

. Когда вы создаете модель сущности из базы данных с помощью FK, она всегда будет генерировать ссылки на сущности. Если вы не хотите их использовать, вы должны вручную изменить файл EDMX и добавить свойства, представляющие FK. По крайней мере, это было в Entity Framework v1, где допускались только независимые ассоциации.

Entity framework v4 предлагает новый тип связи, называемый ассоциацией внешних ключей. Наиболее очевидным различием между независимой и внешней ключевой ассоциацией является класс Order:

public class Order
{
    public int ID { get; set; }
    public int CustomerId { get; set; }  // <-- Customer ID
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

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

Независимая ассоциация

  • Она представлена ​​как отдельный объект в ObjectStateManager. У него есть свой EntityState!
  • При создании ассоциации вам всегда нужны энтуиты с обоих концов ассоциации
  • . Эта ассоциация отображается так же, как сущность.

Ассоциация внешних ключей

  • В ObjectStateManager он не представлен как отдельный объект. В связи с этим вы должны следовать некоторым специальным правилам.
  • При создании ассоциации вам не нужны оба конца ассоциации. Достаточно иметь дочерний объект и PK родительского объекта, но значение PK должно быть уникальным. Поэтому при использовании ассоциации внешних ключей вы также должны назначать временные уникальные идентификаторы вновь сгенерированным объектам, используемым в отношениях.
  • Эта ассоциация не отображается, а вместо этого определяет ссылочные ограничения.

Если вы хотите использовать ассоциацию внешних ключей, вы должны отметить Включить столбцы внешнего ключа в модели в Мастере моделей данных сущностей.

Изменить:

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

104
ответ дан Ladislav Mrnka 27 August 2018 в 08:10
поделиться

Я одобряю объектный подход, чтобы избежать ненужных поисков. Объекты свойств могут быть так же легко заполнены, когда вы вызываете свой заводский метод для построения всей сущности (используя простой код обратного вызова для вложенных объектов). Нет никаких недостатков, которые я вижу, кроме использования памяти (но вы бы кешировали свои объекты правильно?). Таким образом, все, что вы делаете, заключается в замене стека на кучу и повышение производительности из-за неэффективности поиска. Надеюсь, это имеет смысл.

4
ответ дан CarneyCode 27 August 2018 в 08:10
поделиться

Используйте оба параметра. И сделайте ваши сущности ссылками виртуальными, чтобы обеспечить ленивую загрузку. Например:

public class Order
{
  public int ID { get; set; }
  public int CustomerID { get; set; }
  public virtual Customer Customer { get; set; } // <-- Customer object
  ...
}

Это избавляет от ненужных поисков БД, позволяет ленивую загрузку и позволяет легко видеть / устанавливать идентификатор, если вы знаете, кем вы хотите. Обратите внимание, что наличие обоих параметров не меняет структуру вашей таблицы.

33
ответ дан Seth Paulson 27 August 2018 в 08:10
поделиться

Независимая ассоциация не работает с AddOrUpdate , которая обычно используется в методе Seed . Когда ссылка представляет собой существующий элемент, она будет вставлена ​​повторно.

// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);

// New order.
var order = new Order { Id = 1, Customer = customer };
db.Set<Order>().AddOrUpdate(order);

В результате существующий клиент будет вставлен повторно, а новый (повторно вставленный) клиент будет связан с новым заказом.


Если мы не используем ассоциацию внешних ключей и не присваиваем идентификатор.

 // Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);

// New order.
var order = new Order { Id = 1, CustomerId = customer.Id };
db.Set<Order>().AddOrUpdate(order);

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

8
ответ дан Yuliam Chandra 27 August 2018 в 08:10
поделиться
Другие вопросы по тегам:

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