ОБНОВЛЕНИЕ: В последнее время я получил несколько голосов по этому поводу, поэтому я решил, что дам людям знать, что совет, который я даю ниже, не самый лучший.С тех пор как я начал заниматься созданием 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)
И с этим предупреждением ... теперь вам нужно идти!