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