ОБНОВЛЕНИЕ: Я получил несколько голосов по этому поводу в последнее время, поэтому я решил, что я дам людям знать, что совет, который я даю ниже, не самый лучший. С тех пор как я начал заниматься созданием Entity Framework со старыми базами данных без ключей, я пришел к выводу, что лучшее, что вы можете сделать BY FAR, это сделать это с помощью обратного кода в первую очередь. Есть несколько хороших статей о том, как это сделать. Просто следуйте им, а затем, когда вы захотите добавить ключ, используйте аннотации данных, чтобы «подделать» ключ.
Например, скажем, я знаю, что моя таблица Orders
, хотя она не имеет первичного ключа, гарантирует, что когда-либо будет только один номер заказа на одного клиента. Так как это первые два столбца в таблице, я бы настроил первые классы кода так:
[Key, Column(Order = 0)]
public Int32? OrderNumber { get; set; }
[Key, Column(Order = 1)]
public String Customer { get; set; }
Делая это, вы в основном обманываете EF, полагая, что существует кластерный ключ, состоящий из OrderNumber и Customer. Это позволит вам делать вставки, обновления и т. Д. На вашем бесключевом столе.
Если вы не слишком знакомы с выполнением обратного Code First, найдите хорошее руководство по Entity Framework Code First. Затем найдите один из них в Reverse Code First (который выполняет Code First с существующей базой данных). Тогда просто возвращайся сюда и посмотри на мой ключевой совет снова. :)
Оригинальный ответ :
Первое: как уже говорили другие, лучший вариант - добавить первичный ключ в таблицу. Полная остановка. Если вы можете сделать это, не читайте дальше.
Но если вы не можете или просто ненавидите себя, есть способ сделать это без первичного ключа.
В моем случае я работал с устаревшей системой (изначально плоские файлы на AS400 портировались в Access, а затем портировались в T-SQL). Поэтому я должен был найти способ. Это моё решение. Следующее работает для меня, используя Entity Framework 6.0 (последний на NuGet на момент написания статьи).
Щелкните правой кнопкой мыши по файлу .edmx в обозревателе решений. Выберите «Открыть с помощью ...», а затем выберите «XML (Text) Editor». Мы собираемся вручную редактировать сгенерированный код здесь.
Посмотрите на строку, как это:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" store:Schema="dbo" store:Name="table_nane">
Снять store:Name="table_name"
с конца.
Изменить store:Schema="whatever"
наSchema="whatever"
Посмотрите под этой строкой и найдите <DefiningQuery>
тег. В нем будет большое старое утверждение. Удалите тег и его содержимое.
Теперь ваша строка должна выглядеть примерно так:
<EntitySet Name="table_name" EntityType="MyModel.Store.table_name" store:Type="Tables" Schema="dbo" />
У нас есть что-то еще, чтобы изменить. Просмотрите ваш файл и найдите это:
<EntityType Name="table_name">
Рядом вы, вероятно, увидите некоторый закомментированный текст, предупреждающий вас о том, что у него не был идентифицирован первичный ключ, поэтому ключ выведен и определение является таблицей / представлением только для чтения. Вы можете оставить его или удалить его. Я удалил это.
Ниже <Key>
тег. Это то, что Entity Framework будет использовать для вставки / обновления / удаления. ТАК УБЕДИТЕСЬ, ЧТО ВЫ ДЕЛАЕТЕ ЭТО ПРАВО. Свойство (или свойства) в этом теге должно указывать на уникально идентифицируемую строку. Например, скажем, я знаю, что моя таблица orders
, хотя она не имеет первичного ключа, гарантирует, что когда-либо будет только один номер заказа на одного клиента.
Так что мой выглядит так:
<EntityType Name="table_name">
<Key>
<PropertyRef Name="order_numbers" />
<PropertyRef Name="customer_name" />
</Key>
Серьезно, не делай этого неправильно. Допустим, что, хотя никогда не должно быть дубликатов, в мою систему попадают две строки с одинаковым номером заказа и именем клиента. Whooops! Вот что я получаю за то, что не использую ключ! Поэтому я использую Entity Framework, чтобы удалить один. Поскольку я знаю, что дубликат - единственный заказ на сегодня, я делаю это:
var duplicateOrder = myModel.orders.First(x => x.order_date == DateTime.Today);
myModel.orders.Remove(duplicateOrder);
Угадай, что? Я просто удалил как дубликат, так и оригинал! Это потому, что я сказал Entity Framework, что order_number / cutomer_name был моим основным ключом. Поэтому, когда я сказал ему удалить duplicateOrder, то, что он делал в фоновом режиме, было что-то вроде:
DELETE FROM orders
WHERE order_number = (duplicateOrder's order number)
AND customer_name = (duplicateOrder's customer name)
И с этим предупреждением ... теперь тебе нужно идти!