AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: База знаний и проекты
DAX
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 05.05.2011, 15:13   #1  
someOne is offline
someOne
Участник
Аватар для someOne
 
173 / 423 (15) +++++++
Регистрация: 11.12.2008
Адрес: Москва
? Обработка DBF через .net
Возможно кому то пригодится NET компонент (DLL) для работы с файлами dbf в Аксапта...

Приимущества данного решения:

- Надежность (не требуется использования "глючных" ADODB, ODBC и так далее.)
- Быстродействие (обработка файла KLADR.DBF (198 тыс записей) заняла 25 секунд, пример - ниже)
- Возможность использования как на сороне клиента, так и на стороне сервера в т.ч. x64

Компонент самописный, взято отсюда: http://www.sql.ru/Forum/actualthread...194256#7194256
(спасибо автору)

Компонент преобразует dbf файл в стандартный объект NET DataTable. Так же умеет делать и обратную процедуру.

Пример использования - ниже. Как и другие NET компоненты, данную DLL перед использованием нужно "прописать" в Reference AOT аксапты.
X++:
static void DBFTest(Args _args)
{
    System.Data.DataTable           dt;
    System.Data.DataRowCollection   rows;
    System.Data.DataRow             row;
    int                             cnt;
    int                             i;
    str                             name;
    str                             code;
    int                             t1, t2;
    ;
    new InteropPermission(InteropKind::ClrInterop).assert();

    try
    {
        t1 = timeNow();
        
        dt = DBFclient.DirectAccess::Load("c:\\kladr.DBF");

        rows = dt.get_Rows();

        cnt = rows.get_Count();
        
        info(strFmt("строк %1", cnt));

        for (i = 0; i < cnt; i++)
        {
            row = rows.get_Item(i);

            name = row.get_Item("name");
            code = row.get_Item("code");
        }
    }
    
    catch (exception::CLRError)
    {
        throw error(AifUtil::getClrErrorMessage());
    }

    catch (exception::Internal)
    {
        throw error("Internal");
    }

    CodeAccessPermission::revertAssert();
    
    t2 = timeNow();
    
    info(strFmt("%1", t2 - t1));
    
}
Привожу саму DLL и проект с ее исходными кодами (возможно пригодится что то исправить...)
Вложения
Тип файла: zip SourceDBFclient.zip (27.7 Кб, 265 просмотров)
Тип файла: zip DBFclient.zip (5.0 Кб, 266 просмотров)
За это сообщение автора поблагодарили: Pustik (5), Ace of Database (4), lev (5), Poleax (4), MikeR (3), gl00mie (10).
Старый 05.05.2011, 15:45   #2  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
Перенес в базу знаний
__________________
Axapta book for developer
Старый 05.05.2011, 15:58   #3  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
См. также http://fastdbf.codeplex.com
За это сообщение автора поблагодарили: someOne (2).
Старый 06.05.2011, 13:37   #4  
someOne is offline
someOne
Участник
Аватар для someOne
 
173 / 423 (15) +++++++
Регистрация: 11.12.2008
Адрес: Москва
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Проверил этот вариант. Мне он понравился больше. Профессиональная разработка, больше возможностей, грамотно сделано....

Некоторые особенности этого варианта:
- штатно нельзя задать кодировку символов файла при чтении
(по умолчанию она в стандартной западной кодировке, а российские файлы DBF кодируются в кодировке 866, в основном). Пришлось "подправить" это в DLL. - прилагается.

- текстовые поля возврашаются без "обрезанных" с права пробелов,
например
X++:
"Адыгея                                  "
из примера в c файлом kladr.dbf

А во остальном этот вариант - очень даже "FastDbf"

Вот пример использования на том же примере...
Файл - 198 тыс строк, время работы примера - 21 секунда, даже быстрее чем предидущий пример!!!

X++:
static void DBFTest(Args _args)
{
    SocialExplorer.IO.FastDBF.DbfFile   dbfFile;
    SocialExplorer.IO.FastDBF.DbfRecord dbfRecord;
    SocialExplorer.IO.FastDBF.DbfHeader dbfHeader;

    int                             cnt;
    int                             i;

    str                             name;
    str                             code;

    int                             name_idx;
    int                             code_idx;

    int                             t1, t2;
    ;
    new InteropPermission(InteropKind::ClrInterop).assert();

    try
    {
        t1 = timeNow();

        dbfFile = new SocialExplorer.IO.FastDBF.DbfFile();

        dbfFile.Open("c:\\KLADR.DBF", System.IO.FileMode::Open);

        dbfHeader = dbfFile.get_Header();

        cnt = dbfHeader.get_RecordCount(); // определяет количество строк в файле

        dbfRecord = new SocialExplorer.IO.FastDBF.DbfRecord(dbfHeader, System.Text.Encoding::GetEncoding(866)); // можно задать кодировку в dbf файле

        // определение порядкового номера столбца по его имени
        name_idx = dbfRecord.FindColumn("name");
        code_idx = dbfRecord.FindColumn("code");

        info(strFmt("строк в файле %1", cnt));

        for (i = 0; i < cnt; i++)
        {
            dbfFile.Read(i, dbfRecord);

            name = dbfRecord.get_Item(name_idx);
            // Для корректного отображения результата по текстовым полям нужно использовать strrTrim для удаления пробелов в конце строки
            name = strRtrim(name);

            code = dbfRecord.get_Item(code_idx);
        }

        dbfFile.Close();
    }

    catch (exception::CLRError)
    {
        error(AifUtil::getClrErrorMessage());

        dbfFile.Close();
    }

    catch (exception::Internal)
    {
        throw error("Internal");
    }

    t2 = timeNow();

    info(strFmt("Время обработки %1", t2 - t1));

}
Проект свободный для коммерческого использования, так что может быть и это пригодится кому то.
Вложения
Тип файла: zip SocialExplorer.FastDBF.dll.zip (9.6 Кб, 281 просмотров)
Старый 06.05.2011, 15:20   #5  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Там не помешают кое-какие косметические улучшения, к примеру, enum'ы, используемые для указания параметров методов, там кое-где объявлены внутри классов - их лучше вынести на уровень namespace'а, чтобы можно было ссылаться на них в коде Х++ (IntelliSense в MorphX тоже по-другому их "не видит"). После этого может потребоваться добавить соотв. namespace в список using в ряде исходников библиотеки, чтобы они нормально компилировались. Плюс, чтобы работать с dbf на сервере, сборка должна быть помещена в GAC, а для этого у нее должно быть это... strong name, т.е. надо будет еще ее подписать. А так да, очень обстоятельно сделано...

Последний раз редактировалось gl00mie; 06.05.2011 в 15:24.
Старый 06.05.2011, 15:56   #6  
someOne is offline
someOne
Участник
Аватар для someOne
 
173 / 423 (15) +++++++
Регистрация: 11.12.2008
Адрес: Москва
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Плюс, чтобы работать с dbf на сервере, сборка должна быть помещена в GAC, а для этого у нее должно быть это... strong name, т.е. надо будет еще ее подписать. А так да, очень обстоятельно сделано...
Помещать в GAC не обязательно. Достаточно поместить DLL файл в папку сервера,
например
X++:
c:\Program Files\Microsoft Dynamics  *\Bin\
Кроме того, после добавления DLL в reference нужен перезапуск сервера. И все будет работать без помещения в глобальный кеш сборок.

По моему так даже проще и надежнее - проще обновлять версии DLL сборок
Старый 01.12.2011, 21:27   #7  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Коллега допилил библиотеку FastDBF, устранив кое-какие косяки, правда, не возьмусь утверждать, сопровождены ли исправления соотв. комментариями.

PS. Библиотека давно и успешно используется в пром. эксплуатации, дала очень серьезный выигрыш в скорости.
Вложения
Тип файла: rar FastDBF.rar (82.6 Кб, 333 просмотров)

Последний раз редактировалось gl00mie; 01.12.2011 в 21:31.
За это сообщение автора поблагодарили: Logger (3), leva (1), pedrozzz (1).
Старый 06.12.2011, 16:34   #8  
cyrus is offline
cyrus
OntargIT
 
22 / 19 (1) ++
Регистрация: 24.06.2002
Адрес: Kiev
Мы тоже ее используем. В промышленной эксплуатации грузим таблицы размером от 60mb, сделали warper и table field mapping. Работает стабильно уже пол-года.
Старый 15.12.2011, 15:00   #9  
alvares is offline
alvares
Участник
 
45 / 12 (1) ++
Регистрация: 27.10.2011
Коллеги, а есть у кого рабочий пример для создания DBF c помощью "FastDbf"

Не могу понять как работать с заголовком DBF, подскажите в чем не прав - пример создает файл нулевой длины и не отпускает его пока открыта АХ.
X++:
static void DBFCreate(Args _args)
{
    SocialExplorer.IO.FastDBF.DbfFile       dbfFile = new SocialExplorer.IO.FastDBF.DbfFile();
    SocialExplorer.IO.FastDBF.DbfRecord     dbfRecord;
    SocialExplorer.IO.FastDBF.DbfHeader     dbfHeader;
    ;

    dbfFile.Create("c:\\tt1.dbf");

    dbfHeader = dbfFile.get_Header();

    dbfHeader.AddColumn("StrCol", SocialExplorer.IO.FastDBF.DbfColumnType::Character, 20, 0);
    dbfHeader.AddColumn("NumCol1", SocialExplorer.IO.FastDBF.DbfColumnType::Number, 15, 3);
    dbfHeader.AddColumn("NumCol2", SocialExplorer.IO.FastDBF.DbfColumnType::Number, 3, 0);
    dbfHeader.AddColumn("DateCol", SocialExplorer.IO.FastDBF.DbfColumnType::Date);
    dbfHeader.AddColumn("BoolCol", SocialExplorer.IO.FastDBF.DbfColumnType::Boolean);
    
    dbfRecord = new SocialExplorer.IO.FastDBF.DbfRecord(dbfHeader, System.Text.Encoding::GetEncoding(1251));
    dbfRecord.set_Item(1, 'Test');
    dbfRecord.set_Item(2, '100.10');
    dbfRecord.set_Item(3, '10');
    dbfRecord.SetDateValue(4,str2datetime('31.12.2010', 123));
    dbfRecord.set_Item(5, '1');

    dbfFile.Write(dbfRecord);
    dbfFile.WriteHeader();
    dbfFile.Close();
}
Спасибо.
Старый 15.12.2011, 16:56   #10  
someOne is offline
someOne
Участник
Аватар для someOne
 
173 / 423 (15) +++++++
Регистрация: 11.12.2008
Адрес: Москва
Цитата:
Сообщение от alvares Посмотреть сообщение
Коллеги, а есть у кого рабочий пример для создания DBF c помощью "FastDbf"

Не могу понять как работать с заголовком DBF, подскажите в чем не прав - пример создает файл нулевой длины и не отпускает его пока открыта АХ.

Спасибо.
Вот вам рабочий пример.

При работе с NET не забывайте о таких особенностях:
1. Ядро аксапты не перехватывает CLR ошибки, поэтому их нужно перехватывать в коде самому, иначе остаются "висеть" инициализированные объекты (в вашем случае захваченные файлы). Со сборкой мусора при использовании CLR не все так просто...
Кроме того вы просто не сможете понять в чем причина ошибки...

2. В NET принято нумерация последовательности объектов (строк, стобцов...) с нуля а не с единицы как в аксапте.

X++:
static void DBFCreate(Args _args)
{
    SocialExplorer.IO.FastDBF.DbfFile       dbfFile = new SocialExplorer.IO.FastDBF.DbfFile();
    SocialExplorer.IO.FastDBF.DbfRecord     dbfRecord;
    SocialExplorer.IO.FastDBF.DbfHeader     dbfHeader;
    ;

    try
    {
        winApi::deleteFile("c:\\tt1.dbf");

        dbfFile.Create("c:\\tt1.dbf");

        dbfHeader = dbfFile.get_Header();

        dbfHeader.AddColumn("StrCol",  SocialExplorer.IO.FastDBF.DbfColumnType::Character, 20, 0);
        dbfHeader.AddColumn("NumCol1", SocialExplorer.IO.FastDBF.DbfColumnType::Number, 15, 3);
        dbfHeader.AddColumn("NumCol2", SocialExplorer.IO.FastDBF.DbfColumnType::Number, 3, 0);
        dbfHeader.AddColumn("DateCol", SocialExplorer.IO.FastDBF.DbfColumnType::Date);
        dbfHeader.AddColumn("BoolCol", SocialExplorer.IO.FastDBF.DbfColumnType::Boolean);

        dbfRecord = new SocialExplorer.IO.FastDBF.DbfRecord(dbfHeader, System.Text.Encoding::GetEncoding(1251));
        

        dbfRecord.set_Item(0, 'Test');
        dbfRecord.set_Item(1, "100");
        dbfRecord.set_Item(2, "10");
        dbfRecord.SetDateValue(3,str2datetime('31.12.2010', 123));
        dbfRecord.set_Item(4, 'f');

        dbfFile.Write(dbfRecord);
        dbfFile.WriteHeader();
        dbfFile.Close();
    }
    catch (Exception::CLRError)
    {
        dbfFile.Close();
        Error(AifUtil::getClrErrorMessage());
    }
}
За это сообщение автора поблагодарили: gl00mie (2), alvares (1).
Старый 21.02.2012, 07:53   #11  
Андрей К. is offline
Андрей К.
Постигающий
 
152 / 10 (1) +
Регистрация: 09.04.2007
Люди, помогите! Зарегистрировал FastDBF через своего клиента AX2009 , положив DLL в папку c:\Program Files\Microsoft Dynamics AX\50\Server\*имя сервера*\Bin\
После чего у меня на машине код импорта DBF отрабатывает на ура, но у других пользователей вылетает ошибка:
Цитата:
Объект "CLRObject" не может быть создан
на этой строке кода
X++:
dbfFile = new SocialExplorer.IO.FastDBF.DbfFile();
АОС перезагружали
CAS используем:
X++:
new InteropPermission(InteropKind::ClrInterop).assert();
в чем может быть проблема?

UPD. проблема решена перемещением выполнения кода на сервер

Последний раз редактировалось Андрей К.; 21.02.2012 в 08:11.
Старый 21.02.2012, 08:11   #12  
kaw is offline
kaw
Участник
 
122 / 35 (2) +++
Регистрация: 23.03.2004
Адрес: Новосибирск
посмотрите:
ClrObject static method invocation error.

или попробуйте пример
CLRObject.new Method
Старый 22.02.2012, 00:12   #13  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5788 (200) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от Андрей К. Посмотреть сообщение
Зарегистрировал FastDBF через своего клиента AX2009 , положив DLL в папку c:\Program Files\Microsoft Dynamics AX\50\Server\*имя сервера*\Bin\
Объект "CLRObject" не может быть создан
UPD. проблема решена перемещением выполнения кода на сервер
Вы, значит, забыли положить сборку также в каталога bin клиента (на всех хостах, где у вас может запускаться код работы с этой сборкой).
За это сообщение автора поблагодарили: farlander (1), Андрей К. (1).
Старый 27.09.2012, 15:30   #14  
handy-comp is offline
handy-comp
Участник
 
96 / 78 (3) ++++
Регистрация: 27.09.2012
При работе с FastDBF рекомендую обязательно использовать dbfRecord.Clear()

На вышеприведенном примере:

X++:
....
bfRecord = new SocialExplorer.IO.FastDBF.DbfRecord(dbfHeader, System.Text.Encoding::GetEncoding(1251));
        
dbfRecord.Clear(); //!!!!!!!!!!!

dbfRecord.set_Item(0, 'Test');
dbfRecord.set_Item(1, "100");
..........
Выявлено что при первой записи неправильно инициализируются некоторые типы полей значениями по умолчанию, что делает файл не читаемым для опять таки некоторых привередливых ПО.
Принудительный вызов dbfRecord.Clear() все лечит
Теги
.net, dbf, fastdbf, законченный пример, полезное

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
UTF8 -> CP866 через .NET подскажите demoded DAX: Программирование 2 02.03.2011 14:23
AX.NET: интеграция .NET-приложений с Аксаптой и (будущие) возможности облачных вычислений gl00mie DAX: Программирование 2 23.04.2010 00:47
Вложение файлов через метод .NET Business Connector (DocuRef, DocuValue) kornix DAX: Программирование 6 18.09.2009 10:36
Как через .NET коннектор удалить записи? Jab Straight DAX: Программирование 6 09.11.2007 18:56
Не могу залогиниться через .NET connector. axy DAX: Программирование 3 06.12.2006 14:04

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 17:52.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.