В этом посте я собираюсь показать, как вы можете вставить объемные данные, используя DataTable из C # и функцию OpenXML, доступную в Sql Server.
Я получил требование, что «Чтение данных из файла Excel, а затем после проверки данных
нажмите все записи в таблице базы данных». Другое дело, когда при вставке данных в базу данных происходит сбой во время вставки записи, я должен откатить всю вставленную запись.
Чтобы выполнить задачу, я сделал следующим образом
OpenXML.
Я создал процедуру, которая использует функцию OpenXML сервера sql, которая позволяет вставлять несколько записей одновременно. OpenXML требует XML-строку записи для вставки данных в базу данных.
ALTER PROCEDURE [dbo].[Ins_Employee]
( @XmlString text )
AS
BEGIN
SET NOCOUNT ON
BEGIN TRANSACTION
Begin Try
DECLARE @XMLDocPointer INT
EXEC sp_xml_preparedocument @XMLDocPointer OUTPUT, @XmlString
INSERT INTO Employee
(Name, Email, PhoneNo)
SELECT Name,Email,PhoneNo
FROM OPENXML(@XMLDocPointer,'/ROOT/DATA',2)
WITH (Name VARCHAR(50),-- '@Name',
Email VARCHAR(50),-- '@Email',
PhoneNo VARCHAR(50) --'@PhoneNo')
EXEC sp_xml_removedocument @XMLDocPointer
COMMIT TRANSACTION
Return 0;
End Try
Begin Catch
ROLLBACK TRANSACTION
End Catch
END
Как вы видите выше, процедура OpenXML использует xmlDocument в качестве входных данных, которые создаются системой, определяют процедуру sp_xml_preparedocument, которая принимает xmlString в качестве входных данных и возвращает XmlDocument.
После того, как OpenXML выполнит задачу вставки sp_xml_removedocument, системная процедура должна удалить этот элемент.
Все записи вставляются в один раз с помощью функции OpenXML, так как я использовал транзакцию, если вставка одной записи не удалась, все вставленные записи получают откат.
Следующая строка кода, используемого для выполнения кода, т.е. хранимой процедуры.
Как вы видите, я передаю Element centric xml в процедуру.
Exec Ins_Employee
'
pranay
pranayamr@gmail.com
99007007
'
Примечание.
Если вы передаете XML-строку как атрибут, ориентированный на нее, как в процедуре, вам нужно определить переменную, чтобы оператор выбора в процедуре был
SELECT Name,Email,PhoneNo
FROM OPENXML(@XMLDocPointer,'/ROOT/DATA',2)
WITH (Name VARCHAR(50) '@Name',
Email VARCHAR(50) '@Email',
PhoneNo VARCHAR(50) '@PhoneNo')
Exec Ins_Employee
'
'
Теперь, после завершения работы с базой данных, кодовая часть приложения выглядит следующим образом.
Загруженный файл Excel, который содержит данные сотрудника
Уровень представления
Следующая функция в уровне представления считывает данные из файла excel, который загружается на сервер.
private void ReadAndInsertExcelData()
{
int i;
bool blValid = true;
OleDbCommand ocmd;
OleDbDataAdapter oda;
DataTable dtDetails;
DataSet dsDetails;
OleDbConnection oconn = new OleDbConnection
(@"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" +
Server.MapPath("~/Upload/MonthlyActual.xls") + ";Extended
Properties='Excel 8.0;HDR=YES;IMEX=1'");
try
{
ocmd = new OleDbCommand("select * from [Sheet1$]", oconn);
oda = new OleDbDataAdapter(ocmd);
dsDetails = new DataSet();
oda.Fill(dsDetails, "DATA");
dtDetails = dsDetails.Tables[0];
dsDetails.DataSetName = "ROOT";
i = 0;
DataRow[] drLst = dtDetails.Select("(Name is null) or (Email is
null) or (PhoneNo is null)");
if (drLst.Count() > 0)
blValid = false;
if (blValid)
{
XMLController xMLController = new XMLController();
xMLController.Ins(BaseLineType, dtDetails);
}
}
catch
{
lblMsg.Text = ex.Message;
lblMsg.ForeColor = System.Drawing.Color.Red;
}
finally
{
lblMsg.Text = "Data Inserted Sucessfully";
oda = null;
dtDetails = null;
dsDetails = null;
}
}
Приведенная ниже функция бизнес-уровня принимает DataTable в качестве входных данных и генерирует XML-строку. Как вы видите ниже, я использовал StringWriter, который использует объект StringBuilder, а DataTable использует StringWriter и записывает XML-строку в объект StringBuilder.
public int Ins(DataTable pImportTable)
{
int IsSuccess = -100;
try
{
StringBuilder sbXMLString = new StringBuilder();
System.IO.StringWriter sw = new System.IO.StringWriter
(sbXMLString);
pImportTable.WriteXml(sw);
DALXML dALManualCost = new DALXML();
dALManualCost.Ins(sbXMLString.ToString());
IsSuccess = dALManualCost.IsSuccess;
}
catch
{
throw;
}
return IsSuccess;
}
Примечание. Вышеуказанный метод создает XML-строку, ориентированную на элемент.
Теперь, если вы хотите записать xml-файл, ориентированный на атрибуты, вам просто нужно заменить строку datatable.WriteXml на приведенный ниже код цикла, также вам не нужно использовать объект StringWriter.
sbXMLString.Append("");
for (int i = 0; i < pImportTable.Rows.Count; i++)
{
sbXMLString.Append("<DATA ");
sbXMLString.Append("Name='" +
pImportTable.Rows[i][0].ToString().Trim() + "' ");
sbXMLString.Append("Email='" + pImportTable.Rows
[i][1].ToString().Trim() + "' ");
sbXMLString.Append("PhoneNo='" +
pImportTable.Rows[i][2].ToString().Trim() + "' ");
sbXMLString.Append(" />");
}
sbXMLString.Append("");
DataLayer
Теперь этот слой вызывает хранимую процедуру, которая передает xmlstring employee в базу данных. Возвращаемый параметр скажет, что его вставка прошла успешно или нет.
public void Ins(string pXMLString)
{
try
{
Database db = CommonHelper.GetDataBaseInstance();
DbCommand cmdXML = db.GetStoredProcCommand
(SP_INSERT_STAGINGMANUALCOSTMONTHLY);
db.AddInParameter(cmdXML, "XmlString", DbType.String,
pXMLString);
db.AddParameter(cmdXML, "ret", DbType.Int32,
ParameterDirection.ReturnValue, "", DataRowVersion.Current,
IsSuccess);
db.ExecuteNonQuery(cmdXML);
IsSuccess = Convert.ToInt32(db.GetParameterValue(cmdXML, "ret"));
}
catch
{
IsSuccess = -100;
throw;
}
}
Примечание: это один метод, который я нашел полезным для ввода большого количества данных в базе данных в одной транзакции. Есть и другие доступные, которые могут быть более эффективными, чем эта.
