XML MSSQL ASP.NET. Часть 1.


Оглавление (нажмите, чтобы открыть):

SQL-инъекции

Во всех приведенных до сих пор примерах работы с базами данных в контексте ASP.NET использовались жестко закодированные значения. Это позволило сделать примеры простыми, прямолинейными и относительно безопасными. Это также означает, что они не слишком реалистичны и не могут продемонстрировать одну из наиболее серьезных опасностей, которая грозит веб-приложениям, взаимодействующим с базой данных — .

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

Рассмотрим пример, показанный на рисунке ниже. В этом примере пользователь вводит идентификатор заказчика, a GridView отображает все строки для этого заказчика. В более реалистичном примере пользователь должен ввести некоторую аутентификационную информацию, такую как пароль. Или же идентификатор пользователя может быть основан на предыдущем экране регистрации, а текстовое поле обеспечит возможности пользователю указать дополнительные критерии наподобие диапазона дат или наименования товара в заказе:

Здесь проблема связана с тем, каким образом выполняется команда. В данном примере оператор SQL строится динамически, с применением приема сборки строки. Значение из текстового поля txtID просто помещается в середину строки. Вот как выглядит этот код, включая разметку страницы:

Пользователь может попытаться подделать оператор SQL. Часто главной целью такой атаки является получение сообщения об ошибке. Если ошибка не обрабатывается правильно, и злоумышленнику передается низкоуровневая информация, она может быть использована для разработки более изощренной атаки. Например, представим, что произойдет, если пользователь введет в текстовом поле следующий текст:

Теперь посмотрим, какой оператор SQL получится в результате:

Этот оператор вернет все записи о заказах. Даже если заказ не был выдан заказчиком ALFKI, все равно условие 1=1 истинно для всех строк. В результате вместо вывода специфической информации о текущем заказчике злоумышленнику передается вся информация:

И если информация, показанная на экране, важна, как, например, номера карточек социального страхования, даты рождения или информация о кредитных картах, это может вылиться в серьезнейшую проблему! Фактически простые атаки внедрением SQL часто являются источником проблем для ведущих компаний, занятых электронной коммерцией. Часто уязвимость заключается не в текстовом поле, а в строке запроса (которая может быть использована для передачи таких данных базы, как уникальный идентификатор, со страницы списка на страницу формы).

Возможны и более сложные атаки. Например, злоумышленник может просто закомментировать остаток оператора SQL, добавив два тире (—). Эта атака специфична для SQL Server, но аналогичная атака возможна и в MySQL, если использовать символ #, и в Oracle, если задействовать точку с запятой (;). Злоумышленник может также применить пакетную команду, чтобы выполнить произвольный оператор SQL. При использовании поставщика данных SQL Server достаточно просто добавить точку с запятой, за которой передать дополнительную команду. Таким образом, можно, например, удалить содержимое другой таблицы, или даже вызвать системную хранимую процедуру SQL Server по имени xp_cmdshell, чтобы запустить произвольную программу из командной строки.

Вот что злоумышленник может ввести в текстовом поле, чтобы предпринять более изощренную атаку внедрением SQL, удалив все строки в таблице Customers:

Как же противостоять атаке внедрением SQL? Следует запомнить несколько хороших правил. Для начала неплохо бы использовать свойство TextBox.MaxLength, чтобы предотвратить чрезмерно длинный ввод, когда в этом нет необходимости. Это уменьшит вероятность того, что в поле ввода кто-то сможет вставить нежелательный большой фрагмент сценария.

В дополнение к этому можно использовать элементы управления проверкой достоверности ASP.NET, чтобы блокировать очевидно недопустимые данные (такие как текст, пробелы или специальные символы в числовых значениях). Более того, необходимо ограничить информацию, выдаваемую в сообщении об ошибке. Если вы перехватили исключение базы данных, то пользователю стоит выдать лишь самое общее сообщение вроде «Ошибка источника данных», а не выдавать полный текст свойства Exception.Message, которое может помочь обнаружить уязвимости системы.

Еще более важно позаботиться об удалении специальных символов. Например, вы можете преобразовать каждую одиночную кавычку в пару одиночных кавычек, таким образом, гарантируя, что они не будут спутаны с разделителями в SQL-операторе:

Конечно, проблем добавится, если вводимый текст действительно должен содержать апострофы. Кроме того, это не исключает полностью возможности атаки внедрением SQL. Замена апострофов предотвращает преждевременное закрытие строки злоумышленником. Однако при построении динамического оператора SQL, который включает числовые значения, для атаки внедрением SQL понадобится лишь одиночный пробел. Эта уязвимость часто (и опасно) игнорируется.

Еще одна хорошая идея — ограничить права учетной записи, от имени которой выполняется доступ к базе данных, чтобы она не имела прав доступа к другим базам данных или запуска расширенных системных хранимых процедур. Тем не менее, это не решает проблему внедрения SQL-сценариев, поскольку процесс, используемый для подключения к базе данных, почти всегда требует более широких привилегий, чем те, что выделяются отдельному пользователю. Ограничивая учетную запись, вы можете предотвратить атаки, связанные, например, с удалением таблиц, но не сможете предотвратить атаки, связанные с хищением информации.

Все описанные выше способы защиты являются дополнительными средствами, которые опытный злоумышленник может легко обойти. Лучший подход состоит в применении параметризованных команд или хранимых процедур, в которых предусмотрена собственная защита от атак внедрением SQL. Соответствующие приемы рассматриваются в последующих разделах.

Использование параметризованных команд

Параметризованная команда — это просто команда, которая использует символы-заполнители в тексте SQL. Заполнитель указывает место для динамически применяемых значений, которые затем пересылаются через коллекцию Parameters объекту Command. Например, следующий оператор SQL:

должен стать чем-то вроде:

Заполнители добавляются раздельно и автоматически кодируются.

Синтаксис параметризованных команд у различных поставщиков выглядит немного по-разному. В поставщике SQL Server предусматривается использованием именованных заполнителей (с уникальными именами). У поставщика OLE DB каждое жестко закодированное значение заменяется вопросительным знаком. В любом случае необходимо предоставить объект Parameter для каждого параметра, который вставляется в коллекцию Command.Parameters. При работе с поставщиком OLE DB следует убедиться, что параметры добавляются в том же порядке, в котором они появляются в строке SQL. Этого не требует поставщик данных SQL Server, поскольку соответствие между параметрами и заполнителями задается с помощью имен.

В следующем примере представлен вариант прежнего запроса, исключающий возможность атаки внедрением SQL:

Если вы предпримете попытку атаки внедрением SQL с этой исправленной версией страницы, то обнаружите, что она не вернет никаких записей. Причина в том, что ни одна позиция заказа не имеет значения идентификатора заказчика, равного текстовой строке « ALFKI’ OR ‘1’=’1 ». Это как раз то поведение, которое нужно.

Вызов хранимых процедур

Параметризованные команды — лишь небольшой шаг от команд в сторону полноценных хранимых процедур. Как известно, хранимая процедура представляет собой пакет из одного или более операторов SQL, сохраненный в базе данных.

Хранимые процедуры подобны функциям в том, что они являются хорошо инкапсулированными блоками логики, которые могут принимать данные (через входные параметры) и возвращать данные (через результирующие наборы и выходные параметры). Хранимые процедуры обладают множеством преимуществ:

Их легко сопровождать. Например, вы можете оптимизировать команды в хранимой процедуре без перекомпиляции приложения, использующего ее. Также они стандартизуют логику доступа к данным в одном месте — в базе данных, — облегчая ее многократное использование согласованным образом разными приложениями. (В терминах объектно-ориентированного программирования хранимые процедуры определяют интерфейс к базе данных.)

Они позволяют реализовать более безопасное обращение с базой данных. Например, вы можете позволить учетной записи Windows, которая запускает ваш код ASP.NET, использовать определенные хранимые процедуры, но ограничить доступ к лежащим в их основе таблицам.

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

В SQL Server предварительно компилируются все команды SQL, включая неподготовленные. Это значит, что вы используете преимущества компиляции независимо оттого, применяете хранимые процедуры или нет. Однако хранимые процедуры все равно имеют тенденцию повышать производительность, поскольку снижают вариантность SQL-операторов. Системам, использующим случайные операторы SQL, часто свойственно применение слегка отличающихся команд для решения похожих задач, что не позволяет серверу эффективно повторно использовать скомпилированные планы выполнения.

Рассмотрим пример SQL-кода, необходимого для создания хранимой процедуры для вставки отдельной записи в таблицу Employees. Этой хранимой процедуры изначально нет в базе данных Northwind, поэтому ее понадобится сначала добавить (с помощью такого инструмента, как SQL Server Management Studio):


Хранимая процедура принимает два параметра — фамилию и имя. Возвращает она идентификатор вновь созданной записи через выходной параметр EmployeeID, который извлекается после оператора INSERT с помощью функции @@IDENTITY. Это — один из примеров простых задач, которые хранимая процедура может дополнительно упростить. Без использования хранимой процедуры было бы довольно неудобно получить автоматически сгенерированное значение идентификатора только что вставленной новой записи.

Чтобы добавить эту хранимую процедуру к тестовой базе данных Northwind, нужно открыть SQL Server Management Studio (Программы Microsoft SQL Server SQL Server Management Studio) и выполнить следующие шаги:

В окне Object Explorer настроить подключение к SQL Server

В этом же окне раскрыть Northwind Programmability Stored Procedures:

Затем нужно щелкнуть правой кнопкой мыши по разделу Stored Procedures и выбрать New Stored Procedure. В окне редактора ввести код процедуры, указанный выше

Выбрать меню Query Execute, чтобы построить и сохранить хранимую процедуру

Далее можно создать команду SqlCommand, которая послужит оболочкой для вызова хранимой процедуры. Эта команда принимает те же три параметра на входе и использует @@IDENTITY для получения и возврата идентификатора новой записи. Так же понадобится добавить параметры хранимой процедуры в коллекцию Command.Parameters. При этом необходимо указать точный тип данных и длину параметра, чтобы они соответствовали деталям в базе данных:

Обратите внимание, что последний параметр является выходным, что позволяет хранимой процедуре вернуть информацию в код. Хотя этот объект Parameter создается аналогично, вы должны удостовериться, что указали его как выходной параметр, установив значение его свойства Direction в Output. Предоставлять значение не нужно.

Этот код выведет следующий текст в метку Label1:

а в таблице Employees появится новая запись (обратите внимание, что я спроектировал хранимую процедуру для вставки строки содержащей всего два поля — FirstName и LastName, хотя в таблице столбцов больше, поэтому остальные поля заполняются значениями по умолчанию. Я это сделал, чтобы упростить пример, хотя в реальном приложении скорее всего придется определять более сложную хранимую процедуру):

Удобным сокращением является метод AddWithValue() коллекции Parameters. Этот метод принимает имя параметра и значение, но никакой информации о типе. Вместо этого он выводит тип из приведенных данных. (Очевидно, что это работает с входными, но не выходными параметрами, поскольку для выходного параметра значение не указывается.) Если не нужно явно выбирать нестандартный тип данных, благодаря такому менее строгому подходу, можно упростить код:

Мастер Йода рекомендует:  Как изменить дизайн вашего сайта, чтобы улучшить конверсию - Dizz.in.ua

Предполагая, что литеральное выражение «Pupkin» является строкой C# из 6 букв, здесь создается объект SqlParameter со значением Size, равным 6 (символов), и SqlDbType, установленным в NVarChar. База данных может при необходимости преобразовывать эти данные, если только вы не попытаетесь вставить их в поле меньшего размера или совершенного иного типа.

Подключение к SQL-server в ASP.NET веб приложении

Добрый день, вечер, ночь, утро многоуважаемые форумчане. Изучаю asp.net.
Есть один вопрос на который я не могу найти ответ.
Строю веб приложение asp.net и хочу использовать sql server хранить там файлы и различные данные по юзерам.
Я хочу научится подключатся программно, как мне это осуществить? Столько всяких способов, я теряюсь хватаюсь за все и понять толком ничего не могу. Помогите пожалуйста, очень прошу.

PS
Если можно то и ссылочку на тьюториал.

03.04.2012, 14:09

sql server и asp.net
есть база с именем NewDataBase и есть таблица в ней NewTable, как читать все данные этой таблицы.

Как сделать, чтоб в веб-приложении asp.net в visual studio 2010 бд Mysql открывалась на любом ПК
Я разрабатываю веб-сайт. БД я создавал в Mysql 5.5.2. Подключение бд к вижуал студио я делал через.

asp.net, ms sql server, visual studio
Здравствуйте, у меня есть приложение в visual studio 2010 (в которое нужно добавлять свои модули) и.

Переустановка MS SQL Server в ASP .NET повлекла проблемы с обращением к БД
После переустановки MS SQL Server в ASP .NET ( Средство администрирования веб-узла (WAT))выдает.

Как грамотно подключить БД SQL Server к проекту ASP.NET
Всем привет. Создал небольшой сервис ASP.NET в VS2015. Состоит из двух страниц: 1) вход в.

03.04.2012, 14:54 2

Есть один способ. Хранить строку подключения в web.config и для любого Connection использовать данную строку.

03.04.2012, 16:35 [ТС] 3 03.04.2012, 20:02 4
03.04.2012, 20:02
05.04.2012, 06:59 [ТС] 5

Добавлено через 21 час 56 минут
скажите пожалуйста, а вот такой код к какому способу относится?

06.04.2012, 18:49 6
06.04.2012, 19:59 [ТС] 7
06.04.2012, 21:49 8
06.04.2012, 21:55 [ТС] 9

Ладно сам разберусь

06.04.2012, 22:09 10

Короче, обьявляешь какую либо компоненту для отображения данных, например GridView.
Грид можно связать с компонентой источника данных — SqlDataSource.
Соответственно ,в момент привязки, SqlDataSource направит запросы , которые ты декларативно прописал, к БД. Если пользователь в GridView будет изменять или удалять данные, то у SqlDataSource будут соответственно отработаны UpdateCommand,DeleteCommand и выполнены соответствующие запросы.

Inserting and Selecting XML data in SQL Server with ASP.NET (C#)

I have a field in a SQL Server database table of datatype XML.

The proposed format is as follows:

Using ASP.NET (C#), I want to add a new entry to the field (which may or may not already have entries in it). I also want to be able to retrieve the last entry (for display on my .aspx page) and the full list of entries (for display on a .xml page).

I’ve been looking about for information/tutorials and most of what I find is exporting data and converting to XML. Can anybody point me to a relevant tutorial or provide some info for me? Ty

Create Dynamic RSS Feed from MS SQL Server using ASP.NET, Part 1: VB.NET

Before I started, let’s get to know what RSS is.

Quoted from Wikipedia.org

RSS is a family of Web feed formats used to publish frequently updated content such as blog entries, news headlines, and podcasts in a standardized format. An RSS document (which is called a “feed,” “web feed,” or “channel”) contains either a summary of content from an associated web site or the full text. RSS makes it possible for people to keep up with web sites in an automated manner that can be piped into special programs or filtered displays.
The benefit of RSS is the aggregation of content from multiple web sources in one place. RSS content can be read using software called an “RSS reader,” “feed reader,” or an “aggregator,” which can be web-based or desktop-based. A standardized XML file format allows the information to be published once and viewed by many different programs.

Q: What benefits of doing this?
A: If you using RSS Feed, you can display it on various RSS Reader software. In my example, I create a dynamically RSS Feed and then I have installed RSS Reader on SharePoint so now I can get content on MS SQL Server to show up on SharePoint without coding anything on SharePoint. You can also apply RSS Feed to other RSS Reader software.

In this article, I’ll show how to create a RSS Feed to gather content from Microsoft SQL Server so that the RSS Feed will be dynamically. The RSS’s content will be changed every time when the data on MS SQL Server have changed. I will use Microsoft Visual Studio 2005, ASP.NET and code in VB.NET and C#. On this post, I’ll cover only VB.NET. For C#, I’ll write in the next post.

First, I’ll prepare a sample content database as a sample feed and create a store procedure that query the content database. Then, I’ll code on MS Visual Studio 2005 to gather feed from the MS SQL database and display them as RSS format. After that, I will publish the content to web site and test if the content shown as RSS Feed.

You can download the completed project on MS Visual Studio 2005 in zipped format – DynamicRSS VB.NET

For the SQL query to create sample database, tbl_Feed

Requirement

  1. Microsoft Visual Studio 2005 (For developing VB.NET and C#)
  2. Microsoft SQL Server as a database server
  3. Internet Information Services (IIS) to test the published website

Section

Step-by-step to create dynamic RSS feed

Create sample database on MS SQL Server

  1. On a database server, create a sample database. In this example, my database server is located at “BKKSQL001\INSTANCE01”. Create a database name as “TestRSS” and table name as “tbl_Feed” with columns as in the figure below.
  2. Fill some sample data on table “tbl_Feed”. See the figure below for example.
  3. Create a new store procedure to query data from table “tbl_Feed” so that you can alter the query without modifying ASP.NET’s code at later.
  4. The database, table and store procedure are like in the figure below.


Create ASP.NET Web Application on MS Visual Studio 2005 (VB.NET)

  1. Open MS Visual Studio 2005, create a new ASP.NET Web Application.
  2. You’ll see the page as the figure below.
  3. Add some variables to the web.config so that these values can be changed without to recompile the project. Right click on Web.config and select Open, you’ll see the page as in the figure below.
  4. Alter

Code Explanation: I have add two variables: “connStr” and “sp_name” which these values will be loaded into the code in next few steps. The first is the connection string to the database server provides with username, password and database name of the SQL Server. The latter is the store procedure name.
Note: I encourage you to implement Windows Authentication for connecting to SQL Server rather than SQL Authentication. But in this tutorial, I’ve just used SQL Authentication to keep the tutorial simple and better to understand. If you want more information about Windows Authentication, see How To: Connect to SQL Server Using Windows Authentication in ASP.NET 2.0.

  • I’ll change view to code so right click on the “Default.aspx” and select “View Code”.
  • Import the required libraries on the top.

    Imports System.Data.SqlClient Imports System.Xml Imports System.Text

    Code Explanation: The first library is used to make connection with the MS SQL Server. The second is for using xml format since RSS is a xml format. The last one is optional.

    Let’s start coding the first of the RSS. Type the following code in to the Page_Load().

    ‘ Load value from web.config Dim sqlCon As String = System.Configuration.ConfigurationManager.AppSettings(«connStr») Dim spName As String = System.Configuration.ConfigurationManager.AppSettings(«sp_name») ‘ Clear any previous output from the buffer Response.Clear() Response.ContentType = «text/xml» ‘ XML Declaration Tag Dim xml As XmlTextWriter = New XmlTextWriter(Response.OutputStream, Encoding.UTF8) xml.WriteStartDocument() ‘ RSS Tag xml.WriteStartElement(«rss») xml.WriteAttributeString(«version», «2.0») ‘ The Channel Tag — RSS Feed Details xml.WriteStartElement(«channel») xml.WriteElementString(«title», «Test RSS Feed») xml.WriteElementString(«link», «http://testLink») xml.WriteElementString(«description», «This is example Feed from SQL Server») xml.WriteElementString(«copyright», «Copyright 2008. All rights reserved.»)

    Code Explanation:

    1. Line 9-11: Load the values from web.config to variables. The name “connStr” and “sp_name” must match in the web.config -> appSettings -> attribute “key”.
    2. Line 13-15: Clear previous output if any and define the content type as “text/xml”.
    3. Line 17-19: Create new XmlTextWriter object for writing xml tag to the output screen(Response.OutputStream). The xml.WriteStartDocument() write the xml declaration with version 1.0 tag like this:

    Test RSS Feed
    http://testLink This is example Feed from SQL Server

    Next, let’s coding on the m >

    Try Dim reader As SqlDataReader Dim cn As New SqlConnection(sqlCon) Dim cmd As New SqlCommand(spName, cn) cmd.CommandType = CommandType.StoredProcedure cn.Open() reader = cmd.ExecuteReader() While reader.Read() xml.WriteStartElement(«item») xml.WriteElementString(«title», reader(1).ToString()) xml.WriteElementString(«description», reader(2).ToString()) xml.WriteElementString(«link», reader(3).ToString()) xml.WriteElementString(«pubDate», reader(4).ToString()) xml.WriteEndElement() End While reader.Close() cn.Close() Catch ex As Exception Response.Write(ex.Message) End Try

    Code Explanation: All the code in this part is wrapped into “Try…Catch” to avoid thrown exception.

    1. Line 33-36: Declare variables for make connection to SQL Server.
    2. Line 38-39: Open connection to SQL Server and execute query by calling a store procedure “sp_GetFeed” (variable sp_name).
    3. Line 40-47: Enter while loop on each return record and write each record to output screen as a item.
    4. Line 49-50: Close the SQL Server’s conntection.

    The last part is about closing the opened tags.

    xml.WriteEndElement() xml.WriteEndElement() xml.WriteEndDocument() xml.Flush() xml.Close() Response.End()

    Code Explanation: These are closing and ending tags

    1. Line 55-56: Close channel and rss tags.
    2. Line 57-59: Close the connection. End the stream of data.
    3. Line 60: Send all result (in buffer) to display on the screen.

    Получение XML-данных с помощью XmlDataSource в ASP.NET 2.0

    Written on 18 Января 2009 . Posted in ASP.NET


    ОГЛАВЛЕНИЕ

    Основы XmlDataSource

    Элемент управления XmlDataSource является посредником для получения XML-данных, к которым потом может быть осуществлен доступ программным путем, либо они могут быть привязаны к элементу управления. Для осуществления доступа к XML-данным с ASP.NET-страницы посредством элемента XmlDataSource, начните с перетаскивания элемента из Toolbox в окно дизайнера (Designer) (элемент XmlDataSource расположен в разделе данных (Data) в Toolbox). Из смарт-тега элемента XmlDataSource, нажмите на ссылку настройки источника данных ( «Configure Data Source») для открытия мастера настройки (Configure Data Source wizard), показанного ниже. Находясь в мастере, вы можете установить три самых полезных свойства элемента XmlDataSource:

      DataFile — указывает файл, содержащий XML-данные, к которым будет осуществлен доступ. Это может быть локальный файл

    /App_Data/XMLFile.xml, либо удаленный файл, к примеру http://msdn.microsoft.com/rss.xml.

  • TransformFile — XML-документы могут быть преобразованы из одной структуры в другую посредством языка разметки известного как XSL Transformations, или XSLT. Если вы хотите преобразовать содержимое XML в DataFile до работы с XML-данными, укажите XSLT-файл для произведения преобразования. Для получения более подробной информации об XSLT прочитайте учебник по XSLT на сайте W3 Schools.
  • XPath — XPath является XML-синтаксисом, используемым для фильтрации содержимого XML-документа, возвращая конкретное значение либо набор узлов. Если вы хотите работать с конкретным набором XML-данных, укажите выражение XPath для ограничения результатов. Читайте учебник по XPath на сайте W3 School для получения большей информации.

    Если у вас нет XML-данных или XSLT сохраненных в файле, вы можете указать необработанный XML или XSLT напрямую из свойств Data и Transform элемента XmlDataSource. Данные свойства невозможно установить посредством мастера настройки источника данных (Configure Data Source), но вместо этого могут быть установлены через окно свойств Properties. (нажмите на элемент XmlDataSource в режиме дизайнера (Designer) и затем нажмите F4.)

    Привязка элемента управления XmlDataSource к элементу управления данными и осуществление доступа к XML-данным
    Как только вы настроите элемент управления XmlDataSource, добавьте элемент управления данными на страницу и установите его свойство DataSourceID в ID элемента управления XmlDataSource (это легко можно выполнить используя выпадающий список в смарт-теге элемента управления). ASP.NET 2.0 предоставляет новые методы привязки данных для осуществления доступа к конкретным значениям либо набору узлов из привязки данных XML к элементу управления данными:

    • XPath(«xpath») — осуществляет доступ к конкретному значению. Для того, чтобы получить следующее значение узла просто сошлитесь на узел в xpath; для атрибута поставьте вначале имени @.
    • XPathSelect(«xpath») — возвращает набор узлов; может быть использована для привязки набора узлов ко вложенному элементу управления данными.

    Вышеперечисленные выражения привязки данных должны быть представлены в пределах шаблонов. Для таких элементов управления, как GridView и DetailsView, которые составлены из полей (как BoundFields, CheckBoxFields и т.д.), используйте TemplateFields для каждого поля, которое вы хотите отобразить.

    Пример 1: Отображение RSS 2.0 ленты в DataList

    RSS (Really Simple Syndication), это XML-формат разработанный для того, чтобы позволить веб-сайтам публиковать свое содержимое. Содержимое может быть с легкостью интегрировано в другие веб-сайты, либо может быть просмотрено кем-то посредством набора настольных приложений. Многие сайты на сегодняшний день используют RSS 2.0 ленту.

    RSS-лента может иметь следующий формат:

    Вкратце, RSS-лента составлена из набора элементов , каждый из которых представляет последнюю опубликованную часть содержимого.

    Для данного примера нам необходимо привязать набор элементов содержимого к DataList. Таким образом, установите свойство DataFile элемента управления XmlDataSource в указатель ресурса источника удаленной RSS 2.0 ленты (к примеру, http://aspnet.4guysfromrolla.com/rss/rss.aspx) и свойство XPath в /rss/channel/item. Данное выражение XPath указывает XmlDataSource на то, чтобы оно вернуло набор элементов , что означает, что DataList-привязка к данному XmlDataSource будет иметь одну запись, созданную для каждого элемента в указанной ленте RSS.

    Далее добавьте DataList и настройте его ItemTemplate на отображение элементов , и

    ). Следующая разметка выполняет это: каждого элемента содержимого, также с ссылкой для чтения содержимого (при помощи значения элемента

    Заметьте как используется синтаксис для получения конкретного значения из текущего узла привязанного к DataList. Поскольку DataList привязан к набору узлов , возвратит значение текущего элемента
    узла .

    После указания ItemTemplate, просмотрите страницу в обозревателе. Следующее изображение показывает результат RSS ленты.

    Пример 2: Привязываем набор узлов ко вложенному элементу управления данными

    Метод XPath(«xpath») позволяет нам привязать конкретное значение из текущего XML-узла, но если нам нужно получить полный набор узлов и привязать его ко вложенному элементу управления, то метод XPathSelect(«xpath») предоставляет данную функциональность. Для того, чтобы продемонстрировать данный метод в использовании мы создали пример, который отображает квитанцию покупки пользователя, где детальная информация покупки отображена в XML-формате. В приложении к данной статье вы найдете файл названный PO.xml в каталоге проекта App_Data. Данный XML-файл содержит информацию об одном заказе, и имеет следующую структуру:

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

    Для отображения информации о клиенте и детали платежа, добавьте FormView и привяжите его к новому элементу XmlDataSource, чье свойство DataFile установлено в

    /App_Data/PO.xml. Не волнуйтесь насчет того, что необходимо настроить свойство XPath. Далее, в ItemTemplate FormView используйте метод XPath(«xpath») для отображения информации клиента и детали платежа:

    Поскольку элемент управления XmlDataSource не имеет указанного значения XPath, к FormView привязан узел . Следовательно, для получения значения элемента из узла нам необходимо использовать выражение XPath /Order/Customer/Name. Для того чтобы получить значение атрибута — orderDate, атрибут в элементе — добавьте к началу названия @ (т.е., /Order/@orderDate).

    Вышеуказанный синтаксис привязки данных отображает информацию о клиенте и цене в FormView. Нам все еще необходимо отобразить набор . Для выполнения этого добавьте элемент GridView в пределах ItemTemplateDataSource набор узлов при помощи следующего синтаксиса: ‘ . >. Далее, в разделе GridView добавьте TemplateField для каждого из пунктов: FormView и присвойте его свойству

    Вывод

    ASP.NET 2.0 предлагает несколько элементов управления для работы с данными различного типа. К примеру, элемент SqlDataSource разработан для работы с информацией в реляционной базе данных. Как мы уже увидели в данной статье, для работы с XML-данными используется элемент XmlDataSource. Элемент управления XmlDataSource может осуществлять доступ к локальным или удаленным XML-файлам, либо может присвоить необработанную XML-информацию свойству Data. Также существуют опциональные свойства TransformFile и XPath, которые могут быть настроены на преобразование либо фильтрацию содержимого XML данных.


    Как только вы настроите элемент XmlDataSource он может быть привязан к элементу управления данными. XML-содержимое, возвращенное элементом управления XmlDataSource, может быть получено в качестве скалярных значений при помощи XPath(«xpath») или в качестве наборов узлов при помощи XPathSelect(«xpath»). Рассмотрите приложение, доступное в конце данной статьи для получения более подробной информации о коде рассмотренных примеров.

    Данные ASP.NET XML Binding

    Мы можем связать файл XML в элементе управления списком.

    XML-файл

    Существует файл с именем «countries.xml» XML-файл:

    Bind DataSet для управления списком

    Во-первых, импортировать «System.Data» пространства имен. Нам необходимо это пространство имен для работы с объектами DataSet. Следующая инструкция входит в верхней части страницы .aspx:

    Затем создайте DataSet для файла XML, и при первой загрузке страницы этот XML-файл загрузки DataSet:

    Методы типа данных XML стр. 1

    Он может содержать до 2 Гб данных.

    • query() – используется для извлечения XML фрагментов из XML документов;
    • value() – используется для извлечения значений конкретных узлов или атрибутов XML документов;
    • exist() – используется для проверки существования узла или атрибута. Возвращает 1, если узел или атрибут найден, и 0, если не найден;
    • modify() – изменяет XML документ;
    • nodes() – разделяет XML документ на несколько строк по узлам.

    Методы типа данных XML принимают на вход выражение XPath или запрос XQuery.

    Для примеров в данном учебнике будем использовать базу данных с таблицами, содержащими столбцы типа данных XML.

    Таблица tArtist содержит информацию о музыкальных группах, исполнителях и их альбомах.

    Лучший способ заполнения XML из SQL-запроса в ASP.NET?

    Мне нужно создать службу, которая вернет XML, содержащий данные из базы данных. Поэтому я думаю об использовании ASHX, который будет принимать такие вещи, как диапазон дат и POST-файл XML. Я рассмотрел страницы, извлекающие данные из SQL Server и заполняющие данные для визуального отображения, но никогда в XML для доставки, что это лучший способ сделать это? Также, если ASHX и POST не лучший способ доставки, дайте мне знать . спасибо!

    EDIT: Эти ответы велики и указывают на меня в правильном направлении. Я должен был также упомянуть, что формат XML уже решен, поэтому я не могу использовать автоматически сгенерированный.

    Создан 20 мар. 09 2009-03-20 17:33:38 BigOmega

    6 ответов

    Объединения linq2sqlwith классов XElement, то вдоль линий:

    Linq2SQL будет извлекать данные в одном вызове дб, а обработка XML будет сделана на бизнес-сервере. Это лучше разделяет нагрузку, так как у вас нет сервера sql, выполняющего всю работу.

    Создан 20 мар. 09 2009-03-20 18:09:01 eglasius

    XML MSSQL ASP.NET. Часть 1.

    Ключевое слово OPENXML языка Transact-SQL предоставляет набор строк по XML-документам в памяти, подобный таблице или представлению. OPENXML позволяет получить доступ к XML-данным так, как если бы это был реляционный набор строк. Это делается при помощи представления внутреннего отображения XML-документа в виде набора строк. Записи в наборе строк могут храниться в таблицах базы данных.

    OPENXML может использоваться в инструкциях SELECT и SELECT INTO в любых позициях, где в качестве источника могут присутствовать поставщики наборов строк, представления или функция OPENROWSET. Дополнительные сведения о синтаксисе инструкции OPENXML см. в разделе OPENXML (Transact-SQL).

    Чтобы писать запросы к XML-документу с использованием OPENXML, необходимо сначала вызвать хранимую процедуру sp_xml_preparedocument. Таким образом производится синтаксический анализ XML-документа и возвращается дескриптор для проанализированного документа, готового к использованию. Проанализированный документ является представлением дерева объектной модели документа (DOM) различных узлов в XML-документе. Дескриптор документа передается OPENXML. Затем инструкция OPENXML выдает представление документа в виде набора строк, основываясь на переданных ей аргументах.

    Хранимая процедура sp_xml_preparedocument использует обновленную под SQL версию средства синтаксического анализа MSXML, Msxmlsql.dll. Эта версия средства синтаксического анализа MSXML разработана для поддержки SQL Server и остается обратно совместимой с версией MSXML 2.6.

    Внутреннее представление XML-документа должно быть удалено из памяти посредством вызова системной хранимой процедуры sp_xml_removedocument для освобождения памяти.

    На следующей иллюстрации показан этот процесс.

    Обратите внимание на то, что для понимания OPENXML необходимо иметь общее представление о запросах XPath и XML. Дополнительные сведения о поддержке XPath в SQL Server см. в разделе Использование запросов XPath в SQLXML 4.0.


    Примечание

    OpenXML позволяет параметризовать шаблоны XPath столбцов и строк как переменные. Такая параметризация может привести к включению выражений XPath, если разработчик допускает демонстрацию параметризации внешним пользователям (например, если аргументы предоставляются через вызываемую извне хранимую процедуру). Чтобы избежать подобных потенциально опасных ситуаций, рекомендуется никогда не допускать демонстрации аргументов XPath внешним вызывающим программам.

    В следующем примере показано применение процедуры OPENXML в инструкции INSERT и инструкции SELECT . Образец XML-документа содержит элементы и .

    Сначала вызывается хранимая процедура sp_xml_preparedocument для проведения синтаксического анализа XML-документа. Проанализированный документ является древовидным представлением узлов (элементов, атрибутов, текста и комментариев) в XML-документе. OPENXML ссылается на этот проанализированный XML-документ и выдает представление всех частей этого XML-документа в виде набора строк. Инструкция INSERT , использующая функцию OPENXML , может вставлять данные из такого набора строк в таблицу базы данных. Можно вызывать функцию OPENXML несколько раз, получая и обрабатывая представление в виде набора строк различных частей XML-документа. Например, их можно вставить в различные таблицы. Данный процесс также называют разделение XML-данных по таблицам.

    В следующем примере XML-документ разрезается таким образом, что элементы сохраняются в таблице Customers , а элементы сохраняются в таблице Orders с помощью двух инструкций INSERT . Этот пример также демонстрирует инструкцию SELECT , использующую функцию OPENXML , которая получает элементы CustomerID и OrderDate из XML-документа. Последним шагом обработки является повторный вызов процедуры sp_xml_removedocument . Это позволяет освободить память, выделенную для внутреннего древовидного представления XML, создаваемого в фазе синтаксического анализа.

    На следующем рисунке показано XML-дерево, полученное в результате анализа предыдущего XML-документа и созданное с помощью хранимой процедуры sp_xml_preparedocument.

    К числу аргументов OPENXML относятся:

    дескриптор XML-документа (idoc);

    выражение XPath для идентификации узлов, которые должны быть сопоставлены со строками (rowpattern);

    описание набора строк, который должен быть создан;

    сопоставление столбцов набора строк и узлов XML;

    Обработка XML-документа (idoc)

    Дескриптор документа возвращается хранимой процедурой sp_xml_preparedocument.

    Выражение XPath для распознавания узлов, подлежащих обработке (rowpattern)

    Выражение XPath, указанное аргументом rowpattern , распознает набор узлов в XML-документе. Каждый узел, распознанный rowpattern , соотносится с отдельной строкой в наборе строк, созданном OPENXML.

    Узлами, распознанными выражением XPath, могут быть любые узлы XML в XML-документе. Если rowpattern распознает набор элементов в XML-документе, в наборе строк выделяется по одной строке для каждого распознанного узла. Например, если rowpattern приводит к атрибуту, создается строка для каждого узла атрибута, выбранного rowpattern.

    Описание набора строк, который должен быть сформирован

    Схема набора строк используется OPENXML для создания результирующего набора строк. Можно использовать нижеследующие параметры при указании схемы набора строк.

    Использование формата краевой таблицы

    Для указания схемы набора строк следует использовать формат краевой таблицы. Не используйте предложение WITH.

    При этом OPENXML возвращает набор строк в формате краевой таблицы. Ее так называют потому, что каждый край проанализированного XML-документа сопоставляется со строкой в наборе строк.

    Краевые таблицы представляют внутри отдельной таблицы подробную структуру XML-документа. Структура включает в себя имена элементов и атрибутов, иерархию документа, пространства имен и инструкции по обработке. Формат краевой таблицы позволяет получать дополнительные сведения, не отображаемые в метасвойствах. Дополнительные сведения о метасвойствах см. в разделе Specify Metaproperties in OPENXML.

    Дополнительные сведения, предоставляемые краевой таблицей, позволяют сохранять и запрашивать тип данных элемента и атрибута, тип узла, а также сохранять и запрашивать сведения о структуре XML-документа. С учетом этих дополнительных сведений может стать возможным построение собственной системы управления XML-документами.

    Используя краевую таблицу, можно писать хранимые процедуры, которые рассматривают XML-документы как входные данные большого двоичного объекта (BLOB), создают краевую таблицу, а затем извлекают и анализируют документ на более детальном уровне. Этот детальный уровень может включать в себя выявление иерархии документа, имен элементов и атрибутов, пространств имен и инструкций по обработке.

    Краевая таблица также может служить форматом хранения для XML-документов, если сопоставление с другими реляционными форматами нелогично, и поле ntext не обеспечивает достаточными структурными данными.

    В ситуациях, когда возможно использование синтаксического анализатора XML для исследования XML-документа, можно вместо этого применить краевую таблицу, чтобы получить те же сведения.

    В следующей таблице описывается структура краевой таблицы.

    Примечание
    Имя столбца Тип данных Описание
    идентификатор bigint Уникальный идентификатор узла документов.

    Корневой элемент имеет значение идентификатора, равное 0. Отрицательные значения идентификаторов зарезервированы.

    parentid bigint Идентифицирует родителя узла. Родительский узел, определенный этим идентификатором, необязательно является родительским элементом. Однако это зависит от типа узла, родительский узел которого определен этим идентификатором. Например, если узел является текстовым, его родительский узел может быть узлом атрибута.

    Если узел находится на верхнем уровне XML-документа, то его столбец ParentID принимает значение NULL.

    node type int Определяет тип узла и является целым числом, соответствующим нумерации типов узла объектной модели XML (DOM).

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

    1 = Узел элемента


    2 = Узел атрибута

    3 = Узел текста

    4 = Узел раздела CDATA

    5 = Узел ссылки на сущность

    6 = Узел сущности

    7 = Узел инструкции по обработке

    8 = Узел комментария

    9 = Узел документа

    10 = Узел типа документа

    11 = Узел фрагмента документа

    12 = Узел нотации

    Дополнительные сведения см. в разделе «Свойство nodeType» в пакете Microsoft XML (MSXML) SDK.

    localname nvarchar(max) Задает локальное имя элемента или атрибута. Принимает значение NULL, если у объекта DOM нет имени.
    prefix nvarchar(max) Префикс пространства имен для имени узла.
    namespaceuri nvarchar(max) URI пространства имен для имени узла. Если значение равно NULL, пространство имен отсутствует.
    datatype nvarchar(max) Действительный тип данных строки элемента или атрибута; в ином случае имеет значение NULL. Тип данных вычисляется на основе встроенного DTD или встроенной схемы
    prev bigint Идентификатор XML предыдущего элемента этого же уровня. Принимает значение NULL, если нет прямого предыдущего одноуровневого элемента.
    text ntext Содержит значение атрибута или содержимое элемента в виде текста. Либо принимает значение NULL, если для записи в краевой таблице не требуется значение.

    Использование предложения WITH для указания существующей таблицы

    Можно использовать предложение WITH, чтобы указать имя существующей таблицы. Чтобы сделать это, просто укажите имя существующей таблицы, схема которой может быть использована OPENXML для создания набора строк.

    Использование предложения WITH для указания схемы

    Можно использовать предложение WITH, чтобы указать полную схему. При указании схемы набора строк указываются имена столбцов, их типы данных и их сопоставление с XML-документом.

    Можно указать шаблон столбца, применив аргумент ColPattern в SchemaDeclaration. Указанный шаблон столбца используется для сопоставления столбца набора строк с узлом XML, определенным rowpattern, а также используется для определения типа сопоставления.

    Если аргумент ColPattern не указан для столбца, столбец набора строк сопоставляется с узлом XML с тем же именем, основываясь на сопоставлении, указанном посредством аргумента flags . Однако если аргумент ColPattern задан как часть указания схемы в предложении WITH, он переопределяет сопоставление, указанное аргументом flags .

    Сопоставление столбцов набора строк и узлов XML

    В инструкции OPENXML можно при необходимости указать тип сопоставления, например атрибутивное или элементное, между столбцами набора строк и узлами XML, определенными посредством rowpattern. Эти данные используются в преобразовании между узлами XML и столбцами набора строк.

    Сопоставление может быть указано двумя способами, в том числе и обоими сразу:

    Используя аргумент flags

    Указание сопоставления посредством аргумента flags предполагает соответствие имен, в котором узлы XML сопоставляются с соответствующими столбцами набора строк, имеющими то же имя.

    Используя аргумент ColPattern

    ColPattern, выражение XPath, указывается как часть SchemaDeclaration в предложении WITH. Сопоставлением, указанным в ColPattern , перекрывается сопоставление, указанное аргументом flags .

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

    ColPattern указывается в следующих ситуациях:

    Имя столбца в наборе строк отличается от имени атрибута или элемента, с которым оно сопоставлено. В этом случае ColPattern используется для определения имени элемента или атрибута в формате XML, с которым сопоставлен столбец набора строк.

    Необходимо сопоставить атрибут метасвойства со столбцом. В этом случае ColPattern используется для определения метасвойства, с которым сопоставлен столбец набора строк. Дополнительные сведения о том, как использовать метасвойства, см. в разделе Определение метасвойств в инструкции OPENXML.

    Оба аргумента: и flags , и ColPattern , являются необязательными. Если сопоставление не указано, предполагается использование атрибутивного сопоставления, которое является значением по умолчанию для параметра flags.

    Атрибутивное сопоставление

    При присвоении параметру flags в OPENXML значения 1 (XML_ATTRIBUTES) указывается атрибутивное сопоставление. Если аргумент flags содержит XML_ ATTRIBUTES, демонстрируемый набор строк предоставляет или потребляет строки, где каждый элемент XML представлен в виде строки. XML-атрибуты сопоставляются с атрибутами, определенными в SchemaDeclaration или предоставленными Tablename в предложении WITH, на основе соответствия имен. Соответствие имен означает, что атрибуты XML, имеющие определенное имя, хранятся в столбце набора строк с тем же именем.


    Если имя столбца отличается от имени атрибута, с которым оно сопоставлено, должен быть указан аргумент ColPattern .

    Если XML-атрибут имеет квалификатор пространства имен, имя столбца в наборе строк должно также иметь квалификатор.

    Сопоставление, ориентированное на элементы

    При присвоении параметру flags в OPENXML значения 2 (XML_ELEMENTS) указывается элементное сопоставление. Оно подобно атрибутивному сопоставлению, за исключением следующих отличий:

    Соответствие имен в примере сопоставления: при сопоставлении столбца с элементом XML с тем же именем выбираются простые подэлементы, если не указан шаблон на уровне столбца. В процессе получения, если подэлемент является составным, поскольку содержит дополнительные подэлементы, столбцу присваивается значение NULL. При этом значения атрибутов подэлементов пропускаются.

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

    Импорт XML-данных в MS SQL server программным способом

    Я 5 больших XML-файлов который я очень хочу проанализировать. Все они слишком большие, чтобы открыть в текстовом редакторе и поэтому я не знаю их схем XML.

    Я попытался импортировать их в SQL server, однако процесс дал мне ошибку, хотя я уверен, что они действительны, поскольку они были получены из очень авторитетных программистов.

    Я также пробовал другие методы, но каждый борется с большие размеры файлов (в MySQL) или указать, что файлы содержат недопустимые символы XML (Доступ И Excel).

    Как я могу чтение и вставка данных программно? можно ли это сделать с помощью SQL-запроса?

    11 ответов

    по состоянию на 2013 год.

    единственный вариант экономии времени, на мой взгляд, для загрузки больших / огромных XML-файлов в SQL Server (как кто-то ранее кратко упоминал), чтобы использовать SQLXML 4.0 библиотека.

    Это решение, которое я принял для загрузки огромных XML-файлов (7Гб в размере) на ежедневной основе. Предыдущий процесс, который использовал манипуляции C# в задаче скрипта, занял несколько часов. Использование sqlxml 4.0 занимает 15-20 минут. Как установить SQLXML 4.0. шаг за шагом!—15здесь. Для практических примеров в том, как это сделать end to end следуйте по этой ссылке MSDN.

    мой XML также имеет вложенные элементы, поэтому он довольно сложный, в результате получается 10 таблиц с 2,5 до 4 миллионами строк каждая (ежедневный файл иногда больше 7 ГБ). Моя работа была основана исключительно на информации, которую я узнал из двух ссылок выше.

    преимущества:

    • создание XSD может занять некоторое время и требует некоторых знаний. Когда я сделал это, я узнал что-то новое, так что это не было настоящим недостатком для меня.
    • видя, насколько прост пакет служб SSIS, ваш менеджер будет иметь впечатление, что вы не сделали никакой работы.
  • для просмотра больших файлов использовать Просмотр Больших Текстовых Файлов, милый маленький драгоценный камень.

    Примечание: вопрос довольно старый, но «проблема» остается горячей. Я добавил этот пост для разработчиков, которые Google, как массовая загрузка XML-файлов в SSIS и земли здесь.

    Он предназначен для предоставления вам SQL-подобный доступ к большим текстовым файлам, включая XML. Что-то вроде

    . должен работать, чтобы вы начали. Кроме того, будьте осторожны, что документация появится в вашем меню «Пуск» вместе с исполняемым файлом после установки-я не думаю, что есть хороший копия на линии.

    вы должны знать схему. Попробуйте загрузить TextPad или что-то подобное для просмотра файлов.

    когда вы знаете схему, вы можете сделать несколько вещей, чтобы получить их в SQL. Одним из подходов было бы использование OpenXML http://msdn.microsoft.com/en-us/library/ms186918.aspx.

    Я широко тестировал синтаксический анализатор MSSQL xml, bcp.exe утилита отлично работает для этого. Трюк придумывает правый Терминатор строки, так как это должно быть значение, которое не может возникнуть в вашем документе. Например, вы можете сделать следующее:

    Ceate простой текстовый файл, содержащий только выбранный разделитель. Например, поместите эту строку в delim.txt:

    затем объедините это до конца экземпляра документа, из командной строки:

    копировать myFile.xml + delim.txt вне.xml / b

    после этого вы можете BCP его в базу данных, как:

    Если документ UTF-16, то замените переключатель-c на-w

    первое, что я сделал, это получить первые X байтов (например, первый 1 МБ) XML-файлов, чтобы я мог взглянуть на них с помощью редактора по моему выбору.

    Если у вас Cygwin установлен у вас уже есть хорошая утилита GNU, чтобы достичь этого:глава

    кроме того, можно найти родной порт самой утилиты GNU здесь: http://unxutils.sourceforge.net/

    для просмотра очень больших файлов, я нашел V просмотрщик файлов чтобы быть отличным.

    Я использовал его для файлов размером до 8 ГБ. Для файлов с фиксированной длиной записи очень легко перемещаться по размеру блока, поскольку он основан на диске.

    обратите внимание, что нет возможности редактирования.

    сказав это, одна из трудностей с XML заключается в том, что это не очень хороший формат для больших «потоков», так как он имеет общее начало и конец структура и синтаксический анализатор, который не может держать весь файл в памяти, могут сделать некоторые довольно причудливые трюки, чтобы убедиться, что он соответствует DTD или схеме.

    вы пробовали использовать OPENROWSET импортировать большие XML-файлы в таблицу SQL Server?

    поскольку у меня нет файлов 5GB под рукой, я не могу проверить это сам.

    есть еще один способ решить эту проблему: потоковая передача Linq-to-Xml. Проверьте это блоге где Джеймс Ньютон-Кинг показывает, как читать XElement один за другим, и серия из двух частей здесь и здесь по той же теме командой Microsoft XML блог.

    вы должны загрузить свой XML в база данных XML, например,Berkeley DB XML или Xindice

    кроме того, я не уверен, что он может масштабироваться до 850mb, но первый объект XML Editor, и библиотека парсера, на которой она построена, может обрабатывать довольно большие файлы.

    и baretail с должен отображать ваши файлы, не нарушая пота.

    Мастер Йода рекомендует:  Динамические поисковые объявления – что нужно о них знать
    Добавить комментарий