powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / BulkCopy в N таблиц из 1 источника
25 сообщений из 44, страница 1 из 2
BulkCopy в N таблиц из 1 источника
    #39666784
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть плоский файл, в каждой строке по ~300 полней.
Есть маппинг полей в файле к полям в таблицах.
смысл в том, чтоб за одну прочитанную строку Reader'ом, добавить в таблицы записи согласно маппингу.
Косяк в том, что BulkCopy принимает в качестве параметров только 1 таблицу и только 1 источник.
Следовательно, мне придется выполнять пакетную вставку для каждой таблички отдельно и каждый раз перечитывать файл источник
Сиквенс у меня сквозной и заранее известный для всех строк, вопрос только в том, как за 1 проход вставить во все таблички записи.
Или придется колхозить свой BulkCopy?
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666796
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman MejtesЕсть маппинг полей в файле к полям в таблицах.как выглядит?
Или ручной формат?
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666809
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesколхозитьразве конвертнуть файл данных или разбить на несколько по числу таблиц хуже чем колхозить?
Всегда лучше подогнать формат под сиквел чем чем сиквел под твой формат.
imho
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666812
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtes,

сделать несложно - вьха + INSTEAD OF Trigger
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666815
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LRRoman Mejtes,

сделать несложно - вьха + INSTEAD OF Trigger
т.е., в эту вьюху и заливать BulkCopy, ну а в триггере уже распихивать по таблицам
Код: sql
1.
2.
3.
4.
5.
6.
7.
create trigger TrInsVw on MyVw instead of insert
as
begin
	insert into tbl1 select c11, c12,... from inserted
	insert into tbl2 select c21, c22,... from inserted
        ...
end
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666817
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LRвьха + INSTEAD OF Trigger прикольно.
Но тогда можно и залить все в одну таблу и раскидать потом.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666819
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123LRвьха + INSTEAD OF Trigger прикольно.
Но тогда можно и залить все в одну таблу и раскидать потом.
Так ведь "instead of", зачем еще в какую-то таблицу? (Во вьюху напрямую нельзя залить, если базовых таблиц несколько).
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666821
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LRТак ведь "instead of", зачем еще в какую-то таблицу? (Во вьюху напрямую нельзя залить, если базовых таблиц несколько).Вернее, вьюха - это лишь оболочка (над таблицей/ами) - заливать можно лишь в таблицы, но можно и _через_ вьюхи (если базовая таблица одна), в т.ч. можно и через такие вот триггеры - вьюха задает формат данных (перечень полей), а в триггере можно уже делать все что угодно, ссылаясь на заливаемые данные как на inserted.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666824
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LR,
Да знаю я что такое триггер.
Просто это уже не совсем импорт.
По мне лучше
util.exe table1
util.exe table2
сделать.
Но выбирать автору.
Мне нравится разнообразие идей.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666829
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesи каждый раз перечитывать файл источник
ничего страшного
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666879
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman MejtesИли придется колхозить свой BulkCopy?
Колхозить свой именно bulk (т.е. аналог BULK INSERT) - проще убиться. TDS-протокол - это то еще развлечение, я это проходил. Проще действительно view+триггер. Или залить во временную таблицу и раскидать обычным T-SQL батчем в одной транзакции.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666880
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtes...
Сиквенс у меня сквозной и заранее известный для всех строк, вопрос только в том, как за 1 проход вставить во все таблички записи.
Или придется колхозить свой BulkCopy?

Варианты: с триггерами, процедурами и вариациями -- сразу нет.

Правильно: Bulk в специальную таблицу импорта с полями 1 к 1, как в файле. Такую таблицу можно даже создавать на лету под каждый такой импорт. Потом, загруженные записи из таблицы перекладываешь как хочешь куда хочешь SQL-инструкциями.

Что это даёт: транзакционность, полный контроль, асинхронность с возможностью отслеживать процесс в любой момент, возможность постобработки, валидации и проверки со всякими джойнами и т.д.

Подходит для большинства задач интеграции больших и средних объёмов данных.

А триггеры, процедуры и прочая ересь, это однозначно бууэээ... Никогда так не делай. Никогда.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666881
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныИли залить во временную таблицу и раскидать обычным T-SQL батчем в одной транзакции.

Только так
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666885
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttПравильно: Bulk в специальную таблицу импорта с полями 1 к 1, как в файле.
Если формат файла не печатала Маша на машинке.
Конвертация файла занимает секунды. Импорт по сети - минуты.
Ну и ещё бывают один ко многим данные. Опять же предварительный конверт файла входного.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666886
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123hVosttПравильно: Bulk в специальную таблицу импорта с полями 1 к 1, как в файле.
Если формат файла не печатала Маша на машинке.
Конвертация файла занимает секунды. Импорт по сети - минуты.
Ну и ещё бывают один ко многим данные. Опять же предварительный конверт файла входного.

Если нарушение типов это одно, тогда это не верный формат файла, забулкать в любом случае не получится, только порциями, дополнительно выделив корректные данные с точки зрения типов.

Остальное лучше делать, когда данные в БД.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666887
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Написать хранимую процедуру добавления одной записи в N-таблиц.

2. Сгенерировать SQL-пакет, содержащий N вызовов этой хранимой процедуры.

3. Не забыть про set nocount on
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666890
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttPetro123пропущено...

Если формат файла не печатала Маша на машинке.
Конвертация файла занимает секунды. Импорт по сети - минуты.
Ну и ещё бывают один ко многим данные. Опять же предварительный конверт файла входного.

Если нарушение типов это одно, тогда это не верный формат файла, забулкать в любом случае не получится, только порциями, дополнительно выделив корректные данные с точки зрения типов.

Остальное лучше делать, когда данные в БД.да.
Плюс еще корпоративная политика.
Иногда БЛ бизнес логика не в базе.
База просто таблички, а вся логика в классах.
Тогда тоже я лучше разобью на 10 файлов одну простынь 300 полей и в потоках в фоне вставлю.
Автору там виднее. Решений миллион.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666891
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А еще, как вариант, сделать для загрузки SSIS-пакет, и запускать его программно. Внутри пакета раскладывать данные в отдельные таблицы. Тогда не нужно будет использовать T-SQL.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666894
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры ПавловныSSIS действительно.
Про ETL забыли.
Это его основная задача как у сабжа.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666895
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123да.
Плюс еще корпоративная политика.
Иногда БЛ бизнес логика не в базе.
База просто таблички, а вся логика в классах.
Тогда тоже я лучше разобью на 10 файлов одну простынь 300 полей и в потоках в фоне вставлю.
Автору там виднее. Решений миллион.

Тут речь не про логику. Логика, где бы она ни была, может работать не так быстро, как простая вставка. Например, банально, подсасывание справочников, проверка на дубли, валидация и т.д. Варианты на триггерах и процедурах ущербны чуть менее, чем полностью. Они конечно работают, и в простейших случаях даже не так уж и медленно.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666897
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123Сон Веры ПавловныSSIS действительно.
Про ETL забыли.
Это его основная задача как у сабжа.

Это при условии, что там MS SQL.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666898
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,
Конечно. У остальных нету AFAIK такой штуки.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666945
Фотография LR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVosttА триггеры, процедуры и прочая ересь, это однозначно бууэээ... Никогда так не делай. Никогда.
Почему? В данном случае (BulkCopy в N таблиц из 1 источника) это (вью+триггер) самое простое и эффективное решение, имхо конечно.
Вью можно сделать лишь "оберткой" для заливаемых данных, т.е., не основывая на каких-либо таблицах. Вот простецкий пример.
t-sql
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
if object_id('dbo.tblA') is not null drop table dbo.tblA
go
create table dbo.tblA(
 ID int not null constraint PK_tblA primary key
,name varchar(100) not null
)
go
if object_id('dbo.tblB') is not null drop table dbo.tblB
go
create table dbo.tblB(
 ID int not null constraint PK_tblB primary key
,name varchar(100) not null
)
go
if object_id('dbo.vw4BulkCopy') is not null drop view dbo.vw4BulkCopy
go
create view dbo.vw4BulkCopy
as
select 0 as [ID], cast('name1' as varchar(100)) as [name1], cast('name2' as varchar(100)) as [name2]
go
create trigger dbo.trInsVw4BulkCopy on dbo.vw4BulkCopy instead of insert
as
begin
	insert into dbo.tblA select [ID], [name1] from inserted
	insert into dbo.tblB select [ID], [name2] from inserted
end
go


c#
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleApp3
{
    class Program
    {
        static string connectionString = @"Data Source=.;Initial Catalog=testdb;Integrated Security=True;";
        static void Main(string[] args)
        {
            TestBulkCopy(1000);
            Console.ReadKey();
        }
        static void TestBulkCopy(int recordscount)
        {
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    conn.Open();
                    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn,
                        SqlBulkCopyOptions.TableLock | SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.UseInternalTransaction, null))
                    {
                        //bulkCopy.ColumnMappings.
                        bulkCopy.DestinationTableName = "dbo.vw4BulkCopy";
                        using (TestBulkCopyReader reader = new TestBulkCopyReader(recordscount))
                        {
                            bulkCopy.WriteToServer(reader);
                            Console.WriteLine($"Donecount={reader.Donecount - 1}");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        public class TestBulkCopyReader : IDataReader
        {
            int _recordscount = 0;
            public int Donecount = 0;

            public TestBulkCopyReader(int recordscount)
            {
                _recordscount = recordscount;
            }

            #region IDataReader members
            public bool Read()
            {
                return ++Donecount <= _recordscount;
            }
            public object GetValue(int i)
            {
                switch (i)
                { 
                    case 0: return Donecount; //ID1
                    case 1: return string.Format($"row {Donecount} for table A");
                    case 2: return string.Format($"row {Donecount} for table B");
                    default: return null;
                }
            }
            public int FieldCount
            {
                get { return 3; }
            }
            public void Dispose()
            {
            }
            public string GetName(int i)
            {
                throw new NotImplementedException();
            }
            public int GetOrdinal(string name)
            {
                throw new NotImplementedException();
            }
            public void Close()
            {
                throw new NotImplementedException();
            }
            public int Depth
            {
                get { throw new NotImplementedException(); }
            }
            public DataTable GetSchemaTable()
            {
                throw new NotImplementedException();
            }
            public bool IsClosed
            {
                get { throw new NotImplementedException(); }
            }
            public bool NextResult()
            {
                throw new NotImplementedException();
            }
            public int RecordsAffected
            {
                get { throw new NotImplementedException(); }
            }
            public bool GetBoolean(int i)
            {
                throw new NotImplementedException();
            }
            public byte GetByte(int i)
            {
                throw new NotImplementedException();
            }
            public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
            {
                throw new NotImplementedException();
            }
            public char GetChar(int i)
            {
                throw new NotImplementedException();
            }
            public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
            {
                throw new NotImplementedException();
            }
            public IDataReader GetData(int i)
            {
                throw new NotImplementedException();
            }
            public string GetDataTypeName(int i)
            {
                throw new NotImplementedException();
            }
            public DateTime GetDateTime(int i)
            {
                throw new NotImplementedException();
            }
            public decimal GetDecimal(int i)
            {
                throw new NotImplementedException();
            }
            public double GetDouble(int i)
            {
                throw new NotImplementedException();
            }
            public Type GetFieldType(int i)
            {
                throw new NotImplementedException();
            }
            public float GetFloat(int i)
            {
                throw new NotImplementedException();
            }
            public Guid GetGuid(int i)
            {
                throw new NotImplementedException();
            }
            public short GetInt16(int i)
            {
                throw new NotImplementedException();
            }
            public int GetInt32(int i)
            {
                throw new NotImplementedException();
            }
            public long GetInt64(int i)
            {
                throw new NotImplementedException();
            }
            public string GetString(int i)
            {
                throw new NotImplementedException();
            }
            public int GetValues(object[] values)
            {
                throw new NotImplementedException();
            }
            public bool IsDBNull(int i)
            {
                throw new NotImplementedException();
            }
            public object this[string name]
            {
                get { throw new NotImplementedException(); }
            }
            public object this[int i]
            {
                get { throw new NotImplementedException(); }
            }
            #endregion
        }
    }
}

...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666960
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LRПочему?ну, он чуть преувеличил.
Все варианты одинаковы).

LRВот простецкий пример.
Права на бд должны быть выше чем одычно.
В продакшене у заказчика могут не дать.
Как вариант плюсов. Минусов.
...
Рейтинг: 0 / 0
BulkCopy в N таблиц из 1 источника
    #39666978
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
LRПочему? В данном случае (BulkCopy в N таблиц из 1 источника) это (вью+триггер) самое простое и эффективное решение, имхо конечно.

Вью, которое на самом деле не вью, а генерация набора колонок. Триггер, который на самом деле выполняет задачи процедуры. Костыль на костыле. С определённого угла зрения, конечно может выглядеть, как "трюк". Тут уже действительно ИМХО ))

Простое, это процедура, как предложил Алексей К.

Эффективное? Нет. Ни разу, я вас умоляю.

Ну и попробуйте булк в свою вью, посмотрим-с, как это у вас заработает.
...
Рейтинг: 0 / 0
25 сообщений из 44, страница 1 из 2
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / BulkCopy в N таблиц из 1 источника
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]