Выполнение INSERT INTO ... SELECT с LINQ to SQL - PullRequest
5 голосов
/ 02 марта 2010

Я пытаюсь выяснить, возможно ли выполнить команду типа "вставить в ... выбрать" с LINQ to SQL. Немного кода LINQ to SQL, который позволил бы мне отправить одну единственную команду SQL в базу данных, которая вставила бы несколько строк в данную таблицу.

Например, как заставить LINQ to SQL отправить следующий оператор T-SQL в базу данных SQL Server?

INSERT INTO Table1 
SELECT Table2.column1 + 1 AS column1, Table2.column2 + 2 AS column2
WHERE Table2.column3 > 100

Конечно, я мог бы достичь этого с помощью функции DataContext.ExecuteCommand, но это было бы выполнено немедленно, без использования автоматической обработки транзакций, которую вы получаете с DataContext.SubmitChanges. У меня есть ряд обновлений, кроме этого, и я хотел бы, чтобы все они откатывались в случае ошибки.

Есть идеи?

ОБНОВЛЕНИЕ: Вот фактический код:

        var bs_prep =
            from b in dc.T_EDR_FILEBODies
            join
            unpaid in dc.V_UNPAIDs
            on
                b.NUM_ADC.Substring(1, 9) equals unpaid.NOCONT
            join
            acordo in dc.T_ACORDOS_RECOM_APREs
            on
                Convert.ToInt32(b.NUM_ADC.Substring(1, 9)) equals acordo.ID_Contrato
            where
                b.ID_EDR == id_edr
                &&
                (
                    unpaid.NUM_INCUMPRIMENTOS <= max_unpaid_consec
                    &&
                    unpaid.TOTAL_NUM_INCUPRIMENTOS <= max_unpaid_nonconsec
                )
                ||
                (
                    acordo.Activo == true
                    &&
                    acordo.Data_Recomeco <= now
                )
            select new
                {
                    ID_EDR = id_edr_filt,
                    NUM_LINHA = b.NUM_LINHA,
                    CODREJ = b.CODREJ,
                    HDT = b.HDT,
                    IMPORT = b.IMPORT,
                    NIB_DEV = b.NIB_DEV,
                    NUM_ADC = b.NUM_ADC,
                    REF_DD_BC = b.REF_DD_BC,
                    REF_MOV = b.REF_MOV
                }
            ;


        dc.T_EDR_FILEBODies.InsertAllOnSubmit(
            bs_prep.Select(
                b => new T_EDR_FILEBODY{
                    CODREJ = b.CODREJ,
                    HDT = b.HDT,
                    ID_EDR = b.ID_EDR,
                    IMPORT = b.IMPORT,
                    NIB_DEV = b.NIB_DEV,
                    NUM_ADC = b.NUM_ADC,
                    NUM_LINHA = b.NUM_LINHA,
                    REF_DD_BC = b.REF_DD_BC,
                    REF_MOV = b.REF_MOV
                }
            )
        );

Быстрое объяснение: Сущность T_EDR_FILEBODies отображается в таблицу базы данных, в которой в основном хранится содержимое некоторых текстовых файлов, которые мы импортируем. Одна запись соответствует одной строке в текстовом файле.

Я пытаюсь создать отфильтрованную версию содержимого файла, скопировав записи из одного файла, присвоив им новый идентификатор файла (ID_EDR=id_edr_filt), но отфильтровав некоторые строки. Объекты LINQ to SQL являются прямыми сопоставлениями с таблицами базы данных. До сих пор я не добавил код в мой текстовый текст. У них действительно есть первичные ключи, иначе я не смог бы делать вставки на них (я где-то читал, что смог бы избавиться от этого исключения, если бы избавился от первичных ключей, но, как вы можете видеть, это не работа в моем случае).

Когда я запускаю его, я получаю следующее исключение: InsertAllOnSubmit:

Явное построение типа сущности 'T_EDR_FILEBODY' в запросе не допускается.

Полагаю, я понимаю, что явное построение сущности внутри запроса было бы проблематично. Объекты, возвращаемые запросами, имеют отслеживание изменений, изменения вызываются в базу данных при вызове submitchanges. Но как вы могли бы перевести в базу данных изменения в сущности, созданной на стороне клиента? Но значит ли это, что вы никогда не сможете выполнить команду типа INSERT INTO ... SELECT, используя LINQ to SQL?

1 Ответ

0 голосов
/ 02 марта 2010

Вы можете использовать

ctx.Table1.InsertAllOnSubmit(
    mySelectEnumeration.Select(x => new Table1DT { ... })
);
  • InsertAllOnSubmit вставляет несколько записей в таблицу Linq to SQL.
  • mySelectEnumeration - это запрос, который выбирает элементы для вставки.
  • Select(new Table1DT { ... }) - это преобразование, необходимое для преобразования типа данных выбранного вами запроса в тип данных таблицы.

В качестве альтернативы вы можете использовать метод ExecuteCommand и управлять транзакцией вручную.

using (var ctx = new DataClasses1DataContext()) {
    ctx.Connection.Open();
    using (ctx.Transaction = ctx.Connection.BeginTransaction()) {
        ctx.ExecuteCommand("sqlcommand");
        ctx.Transaction.Commit();
    }
}

Или используя область транзакции:

using (var ctx = new DataClasses1DataContext()) {
    using (var scope = new TransactionScope()) {
        ctx.ExecuteCommand("sqlcommand");
        scope.Complete();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...