#c# #sql #.net #.net-core #entity-framework-core
#c# #sql #.net #.net-ядро #entity-framework-core
Вопрос:
У меня есть таблица базы данных с объектами. Объекты имеют PK и уникальный индекс с 4 свойствами. Что я хочу сделать, это добавить новый объект в БД и переместить дубликат «старого» объекта из другой таблицы, известной как «История».
Поэтому, когда я загружаю новый csv-файл, я хочу получить все существующие объекты в БД, которые являются дубликатами объектов в новом csv-файле.
Файлы csv могут быть большими и содержать более 10 тыс. объектов, поэтому требуется много времени, чтобы просмотреть их и проверить, существует ли индекс / идентификатор в базе данных.
Я пытался сохранить объекты с уникальным индексным ключом, но не знаю, как получить уже существующие объекты.
Скриншоты для справки:
Комментарии:
1. Заботитесь ли вы о производительности? Или просто нужно это через чистый EF?
2. Я действительно забочусь о производительности. Я использую ef, так как это единственное, что я знаю.
3. Что ж, я подготовлю образец со сторонним расширением EF Core. Какую базу данных вы используете?
4. Azure Sql Server
5. Также добавьте свой класс сущности. Проще всего будет показать, что делать.
Ответ №1:
Поскольку ядро EF не поддерживает массовые операции по соображениям производительности, лучше сделать это с помощью стороннего расширения (отказ от ответственности, я один из создателей) https://github.com/linq2db/linq2db.EntityFrameworkCore
Для быстрого чтения CSV я предлагаю эту библиотеку https://github.com/mgholam/fastCSV Он будет непрерывно загружать файл через IEnumerable, не используя много памяти.
Лучше реализовать такую вставку с помощью временной таблицы:
var items = ... // you have read CSV file and created enumeration of objects, let's name them SomeItem
using var db = ctx.CreateLinqToDBConnection();
using var temp = db.CreateTempTable("#to_inject", items);
var queryToHistory =
from s in db.GetTable<SomeItem>()
from t in temp.InnerJoin(t => t.key1 == s.Key1 amp;amp; t.Key2 == s.Key2 amp;amp; t.Key3 == s.Key3)
select s;
using var tran = db.BeginTransaction();
// inserting into History table
queryToHistory.Insert(db.GetTable<SomeItemHistory>(), s => new SomeItemHistory
{
Key1 = s.Key1,
Key2 = s.Key2,
Key3 = s.Key3,
Value1 = s.Value1,
Value2 = s.Value2,
...
});
// inserting new records or update existing
db.GetTable<SomeItem>()
.Merge()
.Using(temp)
.OnTargetKey()
.InsertWhenNotMatched()
.UpdateWhenMatched()
.Merge();
tran.Commit();
Комментарии:
1. Это сработало хорошо! Но при создании «CreateTempTable». В нем говорится, что идентификатор должен быть числовым числом. Есть ли способ изменить это?
2. Ну, какая сущность? Какой тип
Id
в базе данных?3. Лучше обновите ваш вопрос с помощью классов и DDL для таблиц.