Десериализовать классы XML в один класс для записи в базу данных - PullRequest
0 голосов
/ 29 апреля 2019

Я пытаюсь десериализовать XML и сохранить результаты в базе данных, используя структуру сущностей.

Первый раздел кода просто для получения необходимого XML-файла из API. Пожалуйста, смотрите ниже:

    public static void Main()
    {
        Program semoAPI = new Program();

        using (WebClient webClient = new WebClient())
        {
            WebClient n = new WebClient();


            //Bid Ask Curves
            var bidAskCurves = n.DownloadString("https://reports.semopx.com/api/v1/documents/static-reports?" +
            "page=1&page_size=1&order_by=ASC&ReportName=Bid/Ask%20Curves&Group=Market%20Data");

            semoReports = JsonConvert.DeserializeObject<SemoReports>(bidAskCurves);

            Console.WriteLine("Bid Ask Curves Report: ");

            Console.WriteLine(semoReports.ResourceBaseUri + "/" + semoReports.Items[0].ResourceName);

            string bidAskCurvesXML = semoReports.ResourceBaseUri + "/" + semoReports.Items[0].ResourceName;

            XDocument bacDoc = XDocument.Load(bidAskCurvesXML);

            //Execute DeserializeBidAskCurves
            semoAPI.DeserializeBidAskCurves(bidAskCurvesXML);
        }
    }

Ниже описана настройка моего класса, содержащего нужные мне элементы XML:

namespace SEMO_app
{
    [XmlRoot("BidAskCurves")]
    public class BidAskCurves
    {
        [Key]
        public int ReportID { get; set; }

        [XmlElement("MarketArea")]
        public MarketArea[] MarketAreas{ get; set; }
    }

    public class MarketArea
    {
        public string MarketAreaName { get; set; }

        [XmlElement("DeliveryDay")]
        public DeliveryDay[] DeliveryDays { get; set; }
    }

    public class DeliveryDay
    {
        public string Day { get; set; }

        [XmlElement("TimeStep")]
        public TimeStep[] TimeSteps{ get; set; }
    }

    public class TimeStep
    {
        public string TimeStepID { get; set; }

        [XmlElement("Purchase")]
        public Purchase[] Purchases { get; set; }
    }

    public class Purchase
    {
        public string Price { get; set; }

        public string Volume { get; set; }
    }
} 

Отсюда я хотел бы десериализовать XML и сохранить информацию в базе данных. Ниже приведен код, который у меня есть, который десериализует XML и возвращает результаты обратно в console.writesection.

Однако я не могу сохранить эти значения в таблице базы данных. Код соответствует и выполняется нормально и обновляет таблицу базы данных, однако таблица содержит только столбец идентификатора отчета. Где бы я хотел, чтобы он содержал элементы, перечисленные в разделе console.write.

        private void DeserializeBidAskCurves(string filename)
    {
        //Visual only not needed
        Console.WriteLine("\n" + "Reading BidAskCurves XML File");
        Console.WriteLine("===========================================================");

        // Create an instance of the XmlSerializer.
        XmlSerializer serializer = new XmlSerializer(typeof(BidAskCurves));

        // Declare an object variable of the type to be deserialized.
        BidAskCurves item;

        using (XmlReader reader = XmlReader.Create(filename))
        {
            // Call the Deserialize method to restore the object's state.
            item = (BidAskCurves)serializer.Deserialize(reader);

            //Write out the properties of the object. (Visual Only, not needed)
            Console.Write(
                item.MarketAreas[0].MarketAreaName + "\t" +
                item.MarketAreas[0].DeliveryDays[0].Day + "\t" +
                item.MarketAreas[0].DeliveryDays[0].TimeSteps[0].TimeStepID + "\t" +
                item.MarketAreas[0].DeliveryDays[0].TimeSteps[0].Purchases[0].Price + "\t" +
                item.MarketAreas[0].DeliveryDays[0].TimeSteps[0].Purchases[0].Volume);


            //write the properties to the db 
            using (SEMOContext context = new SEMOContext())
            {
                context.BidAskCurvesReports.Add(item);
                context.SaveChanges();
            }
        }
    }

Ссылка на XML-файл: https://reports.semopx.com/documents/BidAskCurves_NI-IDA3_20190401_20190401161933.xml

Спасибо за любую помощь заранее.

Ответы [ 2 ]

0 голосов
/ 29 апреля 2019
    static void Main(string[] args)
    {
        using (WebClient webClient = new WebClient())
        {
            //Bid Ask Curves
            var bidAskCurves = webClient.DownloadString("https://reports.semopx.com/documents/BidAskCurves_NI-IDA3_20190401_20190401161933.xml");

            var serializer = new XmlSerializer(typeof(BidAskCurves));
            BidAskCurves result;

            using (TextReader reader = new StringReader(bidAskCurves))
            {
                // here it is
                result = (BidAskCurves)serializer.Deserialize(reader);
            }
        }

        Console.ReadKey();
    }

и объекты xml:

[XmlRoot(ElementName = "Purchase")]
public class Purchase
{
    [XmlElement(ElementName = "Price")]
    public string Price { get; set; }
    [XmlElement(ElementName = "Volume")]
    public string Volume { get; set; }
}

[XmlRoot(ElementName = "Sell")]
public class Sell
{
    [XmlElement(ElementName = "Price")]
    public string Price { get; set; }
    [XmlElement(ElementName = "Volume")]
    public string Volume { get; set; }
}

[XmlRoot(ElementName = "TimeStep")]
public class TimeStep
{
    [XmlElement(ElementName = "TimeStepID")]
    public string TimeStepID { get; set; }
    [XmlElement(ElementName = "Purchase")]
    public List<Purchase> Purchase { get; set; }
    [XmlElement(ElementName = "Sell")]
    public List<Sell> Sell { get; set; }
}

[XmlRoot(ElementName = "DeliveryDay")]
public class DeliveryDay
{
    [XmlElement(ElementName = "Day")]
    public string Day { get; set; }
    [XmlElement(ElementName = "TimeStep")]
    public List<TimeStep> TimeStep { get; set; }
}

[XmlRoot(ElementName = "MarketArea")]
public class MarketArea
{
    [XmlElement(ElementName = "MarketAreaName")]
    public string MarketAreaName { get; set; }
    [XmlElement(ElementName = "DeliveryDay")]
    public DeliveryDay DeliveryDays { get; set; }
}

[XmlRoot(ElementName = "BidAskCurves")]
public class BidAskCurves
{
    [XmlElement(ElementName = "MarketArea")]
    public MarketArea MarketAreas { get; set; }
}

EDIT

цикл по результату:

foreach (var item in deliveryDays.TimeStep)
{
    // var day = deliveryDays.Day
    var timeStep_Purchase = item.Purchase;
    var timeStep_Sell = item.Sell;
    var timeStep_Id = item.TimeStepID;
}
0 голосов
/ 29 апреля 2019

Изначально трудно понять, в чем проблема на самом деле?

Но после посещения URI, сгенерированного

string bidAskCurvesXML = semoReports.ResourceBaseUri + "/" + semoReports.Items[0].ResourceName;

И это https://reports.semopx.com/documents/BidAskCurves_NI-IDA3_20190401_20190401161933.xml

Итак, используемая вами структура класса отличается от xml, сгенерированного URI.

Вам необходимо использовать структуру ниже класса для вашего xml

[XmlRoot("Purchase")]
public class Purchase
{
    [XmlElement("Price")]
    public string Price { get; set; }
    [XmlElement("Volume")]
    public string Volume { get; set; }
}

[XmlRoot("Sell")]
public class Sell
{
    [XmlElement("Price")]
    public string Price { get; set; }
    [XmlElement("Volume")]
    public string Volume { get; set; }
}

[XmlRoot("TimeStep")]
public class TimeStep
{
    [XmlElement("TimeStepID")]
    public string TimeStepID { get; set; }
    [XmlElement("Purchase")]
    public List<Purchase> Purchase { get; set; }
    [XmlElement("Sell")]
    public List<Sell> Sell { get; set; }
}

[XmlRoot("DeliveryDay")]
public class DeliveryDay
{
    [XmlElement("Day")]
    public string Day { get; set; }
    [XmlElement("TimeStep")]
    public List<TimeStep> TimeStep { get; set; }
}

[XmlRoot("MarketArea")]
public class MarketArea
{
    [XmlElement("MarketAreaName")]
    public string MarketAreaName { get; set; }
    [XmlElement("DeliveryDay")]
    public DeliveryDay DeliveryDay { get; set; }
}

[XmlRoot("BidAskCurves")]
public class BidAskCurves
{
    [XmlElement("MarketArea")]
    public MarketArea MarketArea { get; set; }
}

И после использования вышеуказанной структуры классов с XmlSerializer доступно всего 12 временных меток

Использование:

XmlSerializer serializer = new XmlSerializer(typeof(BidAskCurves));

BidAskCurves item;

using (XmlReader reader = XmlReader.Create("https://reports.semopx.com/documents/BidAskCurves_NI-IDA3_20190401_20190401161933.xml"))
{
    item = (BidAskCurves)serializer.Deserialize(reader);

    //Your code to add above parsed data into database.
}

Вывод: (из отладчика)

enter image description here

Edit1:

Чтобы добавить объем и цену первой покупки, а затем объем и цену продажи,

...

item = (BidAskCurves)serializer.Deserialize(reader);

foreach (var ts in item.MarketArea.DeliveryDay.TimeStep)
{
    BidAskCurvesData bidAskCurvesData = new BidAskCurvesData
    {
        ReportID = 123,
        MarketAreaName = item.MarketArea.MarketAreaName,
        Day = item.MarketArea.DeliveryDay.Day,
        TimeSetID = ts.TimeStepID,
        PurchasePrice = ts.Purchase[0].Price,
        PurchaseVolume = ts.Purchase[0].Volume,
        SellPrice = ts.Sell[0].Price,
        SellVolume = ts.Sell[0].Volume
    };

    using (SEMOContext context = new SEMOContext())
    {
        context.BidAskCurvesReports.Add(item);
        context.SaveChanges();
    }
}
...