PostgreSQLCopyHelper Массовая вставка Postgresql Таблица C# Файл с фиксированной шириной

Я пытаюсь Bukl Вставить данные из файла с фиксированной шириной в таблицу Postgresql. Я наткнулся на библиотеку PostgreSQLCopyHelper

https://github.com/bytefish/PostgreSQLCopyHelper

Это моё обновление действия в контроллере (обновлено 15.06.17)

        ProductData  pd = new ProductData();

        public ActionResult Update(q_product q_product, HttpPostedFileBase upload)
        {
        ProductData pd;
        var entities = new List<ProductData>();
        PostgreSQLCopyHelper<ProductData> insert;                       

        try
        {
            if(ModelState.IsValid && upload != null)
            {                    
                //uploaded file
                Stream stream = upload.InputStream;

                //need to use BULK INSERT or MULTIPLE INSERT at this point;                    

                //get the properties (columns) as set in ProductData.cs
                using (var fdr = new FileDataReader<ProductData>(stream))
                {
                    //read and get each line on imported file
                    while ((pd = fdr.ReadLine()) != null)
                    {
                        //Lets populate insert
                        //map table columns with properties
                        insert = new PostgreSQLCopyHelper<ProductData>("public", "q_product")
                            .MapUUID("q_guid", x => Guid.NewGuid())
                            .MapText("q_barcode", x => pd.barcode)
                            .MapText("q_description", x => pd.description)
                            .MapText("q_import_size", x => pd.size)
                            .MapNumeric("q_stocklevel", x => pd.quantity)
                            .MapText("q_import_vatcode", x => pd.vatCode) //vatcode is numeric in DB, this is a String (new column for this test)
                            .MapNumeric("q_casecost", x => pd.cost)
                            .MapNumeric("q_sellprice", x => pd.price);                            

                        //add the populated entries as we iterate through the file
                        entities.Add(pd);

                        using (var connection = new NpgsqlConnection("Host=192.168.0.52;Database=bolo;Username=western;Password=western"))
                        {
                            try
                            {
                                connection.Open();
                                insert.SaveAll(connection, entities);                                    
                                int lineCount = entities.Count();
                                TempData["SuccessMessage"] = lineCount+" Records Inserted!";
                            }
                            catch (Exception er)
                            {                                    
                                TempData["ErrorMessage"] = er.Message;
                                //TempData["ErrorMessage"] = "Error: importing records!";
                            }
                        }
                    }
                }

                return RedirectToAction("Index");
            }
        }

        catch(DataException error)
        {
            TempData["ErrorMessage"] = "Error importing records!";
            ModelState.AddModelError("", error.Message);
        }

        return RedirectToAction("Index");
    }

Файл ProductData.cs

public class ProductData 
{
    [Layout(22, 13)]
    public string barcode;        

    [Layout(49, 25)]
    public string description;

    [Layout(74, 5)]
    public string size;

    [Layout(95, 4)]
    public int quantity;

    [Layout(99, 1)]
    public string vatCode;

    [Layout(108, 7)]
    public decimal cost;

    [Layout(115, 7)]
    public decimal price;

    public override string ToString()
    {            
        return String.Format("string: {0}; string: {1}; string: {2}; int: {3}; string: {4}; decimal {5}; decimal {6}",
                barcode, description, size, quantity, vatCode, cost, price
            );            
    }
}

После отладки

юридические лица

параметр в этой строке в действии обновления

 insert.SaveAll(connection, entities); 

бывает нулевым, поэтому ни одна строка не сохраняется и выдает ошибку "Объект не задан". Теперь из ограниченной документации об этой библиотеке CopyHelper я не могу понять, какой класс или параметр мне нужно сделать IEnumerable, так как SaveAll требует второй параметр IEnumerable

Экран отладки

Как вы можете видеть из экрана отладки, мой pd (ProductData) имеет значения, необходимые для хранения в таблице. Как связать это с параметром IEnumerable, необходимым в методе SaveAll?

Не могу закрыть писателя, строка все еще продолжается, закончите сначала

2 ответа

Решение

Я подозреваю, что вы хотите что-то вроде:

public ActionResult Update(q_product q_product, HttpPostedFileBase upload)
{    
    ProductData pd;
    var entities = new List<ProductData>();
    PostgreSQLCopyHelper<ProductData> insert = null;
    try
    {
        if(ModelState.IsValid && upload != null)
        {                    
            //uploaded file
            Stream stream = upload.InputStream;

            //need to use BULK INSERT or MULTIPLE INSERT at this point;                    

            //get the properties (columns)
            using (var fdr = new FileDataReader<ProductData>(stream))
            {
                //get each line on file
                while ((pd = fdr.ReadLine()) != null)
                {
                    //map table columns with properties
                    insert = insert ?? new PostgreSQLCopyHelper<ProductData>("public","q_product")
                        .MapUUID("q_guid", x => Guid.NewGuid())
                        .MapText("q_barcode", x => this.pd.barcode)
                        .MapText("q_description", x => this.pd.description)
                        .MapText("q_size", x => pd.size) 
                        .MapInteger("q_stocklevel", x => this.pd.quantity)
                        .MapText("q_vatcode", x => pd.vatCode)  
                        .MapMoney("q_casecost", x => this.pd.cost)
                        .MapMoney("q_sellprice", x => this.pd.price);
                    entities.Add(pd);
                }
            }
            using (var connection = new NpgsqlConnection("Host=192.168.0.52;Database=tester;Username=test;Password=test"))
            {
                try
                {
                    connection.Open();
                    insert.SaveAll(connection, entities);                                    
                    TempData["SuccessMessage"] = "Records Inserted!";
                }
                catch (Exception er)
                {
                    TempData["ErrorMessage"] = er.Message;                                    
                    //TempData["ErrorMessage"] = "Error importing records!";
                }
            }

            return RedirectToAction("Index");
        }
    }

    catch(DataException error)
    {
        TempData["ErrorMessage"] = "Error importing records!";
        ModelState.AddModelError("", error.Message);
    }

    return RedirectToAction("Index");
}

Главное изменение - заполнение insert только один раз, а затем добавление записей в entities как вы перебираете загруженные файлы.

Добавление к удивительному и высоко ценимому ответу mjwillis, если вы не видите раздел комментариев. Следующий код приводит все в порядок: измените отображение с

.MapText("q_barcode", x => this.pd.barcode)

в

.MapVarchar("q_barcode", x => x.barcode)

следующее

//map table columns with properties
                        insert = insert ?? new PostgreSQLCopyHelper<ProductData>("public", "q_product")
                            .MapUUID("q_guid", x => Guid.NewGuid())
                            .MapVarchar("q_barcode", x => x.barcode)
                            .MapVarchar("q_description", x => x.description)
                            .MapVarchar("q_import_size", x => x.size)
                            .MapNumeric("q_stocklevel", x => x.quantity)
                            .MapVarchar("q_import_vatcode", x => x.vatCode) 
                            .MapNumeric("q_casecost", x => x.cost)
                            .MapNumeric("q_sellprice", x => x.price);
Другие вопросы по тегам