클라이언트 프론트 엔드가 입력을 기다리고있는 것을 에뮬레이트하기 위해 MySQL 쿼리에서 XML을 포맷하려고합니다. 나는 클라이언트가 요구하는 것을 통제 할 수 없기 때문에 Wireshark 캡처에서 얻은 정보와 일치시켜야합니다. 필자는 데이터 집합에 열을 추가하여이 작업을 수행 할 생각이 없습니다. XML에 추가 된 내용을 검색하고 바꿀 수는 있지만 매우 비슷하지만 많은 쿼리가 있습니다. & 출력 글을 쓸 때, 나는 비례가 잘되는 것을하고 싶다. 불행하게도이 코드는 새로운 프런트 엔드 클라이언트를 작성할 때 현재의 레거시 시스템이 클라이언트 IP 주소 나 고유 한 "ActionID"와 같이 많은 데이터를 추적하지 않기 때문에 코드를 버릴 수 있습니다. 아래에서 참조 할 것입니다. XML로 아무것도하지 않아도됩니다. 모두 MySQL 기반의 쿼리가 될 것입니다. 내 쿼리XML 부모 노드로 사용할 데이터 세트에 열 추가
<PCBDatabaseReply>
<SearchResult>
<SBE_PCB_Data PCBID="53">
<Termination ActionID="97DF" User="UName:192.168.255.255" Date="2012-09-26T13:15:51" PCBID="53">
<Reason>Other</Reason>
</Termination>
</SBE_PCB_Data>
</SearchResult>
</PCBDatabaseReply>
결과는 다음과 같이 :
내 출력이 같은 형식이어야합니다
EventType User Date PCBID Reason
Termination UName 2012-09-26T13:15:51 53 Other
내 출력 XML은 현재 다음과 같습니다 :
<PCBDatabaseReply>
<Termination User="UName" Date="2012-09-26T13:15:51" PCBID="53">
<EventType>Termination</EventType>
<Reason>Other</Reason>
</Termination>
</PCBDatabaseReply>
탈회 태그에서 <SearchResult>
<SBE_PCB_Data PCBID="53">
: 나는 <PCBDatabaseReply> 아래에 몇 가지 상단에
를 주입 할 필요가
string mysqlConnection = "server=server;\ndatabase=database;\npassword=password;\nUser ID=user;";
MySqlConnection connection = new MySqlConnection(mysqlConnection);
connection.Open();
string command = "SELECT eventtypes.EventType, events.User, DATE_FORMAT(events.DateTime,'%Y-%m-%dT%T') AS Date, pcbid.PCBID, getReasons.ItemValue AS Reason " +
"FROM events " +
"INNER JOIN pcbid ON events.PCBID = pcbid.PCBID " +
"INNER JOIN eventtypes " +
"ON events.EventType_ID = eventtypes.EventType_ID " +
"LEFT JOIN getReasons " +
"ON getReasons.Event_ID = events.Event_ID " +
"WHERE eventtypes.EventType = 'termination'";
//create fake "ActionID"
var random = new Random();
string ActionID = String.Format("{0}\"{1:X4}\"", "ActionID=", random.Next(0xffff));
MySqlDataAdapter adapter = new MySqlDataAdapter(command, connection);
DataSet dataSet = new DataSet();
adapter.Fill(dataSet);
//change upper level node name to what's expected in client-speak
dataSet.DataSetName = "PCBDatabaseReply";
//change first child node name to client-speak eventType
dataSet.Tables[0].TableName = dataSet.Tables[0].Rows[0][0].ToString();
StringWriter writer = new StringWriter();
var ds1 = dataSet.Tables[0];
DataColumn dcEventType = ds1.Columns[0];
DataColumn dcUser = ds1.Columns[1];
DataColumn dcDate = ds1.Columns[2];
DataColumn dcPCBID = ds1.Columns[3];
dcEventType.ColumnMapping = MappingType.Element;
dcUser.ColumnMapping = MappingType.Attribute;
dcDate.ColumnMapping = MappingType.Attribute;
dcPCBID.ColumnMapping = MappingType.Attribute;
dataSet.Tables[0].WriteXml(writer, true);
Console.WriteLine(writer.ToString());
:
이 코드를 사용하여 (코드의 가짜 ActionID에서)
ActionID="0xnnnn" & append ":192.168.255.255" to the end of the user name
그리고 적절한 태그 다음 닫기 :
</SBE_PCB_Data>
</SearchResult>
내가 작동하지 않았다 "SBE_PCB_Data"태그에 대한 더미 열을 추가 노력했다. 나는 조상 노드로 XML의 나머지 부분을 빙 돌아 필요
<SBE_PCB_Data>SBE_PCB_Data</SBE_PCB_Data>
:
DataColumn dcSBE_PCB_Data = new DataColumn("SBE_PCB_Data", System.Type.GetType("System.String"), "SBE_PCB_Data", MappingType.Element);
dcSBE_PCB_Data.DefaultValue = "SBE_PCB_Data";
//add to the dataset
dataSet.Tables[0].Columns.Add(dcSBE_PCB_Data);
//move it to the zeroth position
dcSBE_PCB_Data.SetOrdinal(0);
이 그냥로 표시합니다.
결과에 XML을 삽입하는 가장 좋은 방법은 무엇입니까?
편집 : 아래의 훌륭한 예에 따라 리팩토링 ** 편집 : 최종 코드
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Xml.Linq;
using MySql.Data.MySqlClient;
namespace TerminationResults
{
public class SearchResult
{
//all possible event detail tags (test items are excluded)
public string EventType { get; set; }
public string User { get; set; }
public string Date { get; set; }
public string PCBID { get; set; }
public string EAReason { get; set; }
public string ETReason { get; set; }
public string Notes { get; set; }
public string Reason { get; set; }
public string SBEJobNumber { get; set; }
public string SBEModelNumber { get; set; }
public string SBEPN { get; set; }
public string SBESerialNumber { get; set; }
//create fake IP address since we no longer track it
public string UserAndIP
{
get { return String.Format("{0}:192.168.255.255", User); }
set {}
}
//create fake actionID since the originals weren't inserted into the database because they weren't unique.
public string ActionId
{
get { return String.Format("{0:X4}", new Random().Next(0xffff)); }
set {}
}
}
internal class Program
{
private static void Main(string[] args)
{
var searchResults = GetSearchResults();
var xml = TransformList(searchResults);
Console.WriteLine(xml);
Console.ReadLine();
}
public static IEnumerable<SearchResult> GetSearchResults()
{
List<SearchResult> searchResults = new List<SearchResult>();
try
{
const string mysqlConnection = @"server=server;
database=database;
password=password;
User ID=username;";
MySqlConnection conn = new MySqlConnection(mysqlConnection);
conn.Open();
using (conn)
{
string cmd = @"SELECT eventtypes.EventType, events.User,
DATE_FORMAT(events.DateTime,'%Y-%m-%dT%T') AS Date,
pcbid.PCBID,
getEAReasons.ItemValue AS EAReason,
getETReasons.ItemValue AS ETReason,
getReasons.ItemValue AS Reason,
getNotes.ItemValue AS Notes,
getSBEJobNumbers.ItemValue AS SBEJobNumber,
getSBEModelNumbers.ItemValue AS SBEModelNumber,
getSBEPNs.ItemValue as SBEPN,
getSBESerialNumbers.ItemValue as SBESerialNumber
FROM events
INNER JOIN pcbid ON events.PCBID = pcbid.PCBID
INNER JOIN eventtypes
ON events.EventType_ID = eventtypes.EventType_ID
LEFT JOIN getEAReasons
ON getEAReasons.Event_ID = events.Event_ID
LEFT JOIN getETReasons
ON getETReasons.Event_ID = events.Event_ID
LEFT JOIN getReasons
ON getReasons.Event_ID = events.Event_ID
LEFT JOIN getNotes
ON getNotes.Event_ID = events.Event_ID
LEFT JOIN getSBEJobNumbers
ON getSBEJobNumbers.Event_ID = events.Event_ID
LEFT JOIN getSBEModelNumbers
ON getSBEModelNumbers.Event_ID = events.Event_ID
LEFT JOIN getSBEPNs
ON getSBEPNs.Event_ID = events.Event_ID
LEFT JOIN getSBESerialNumbers
ON getSBESerialNumbers.Event_ID = events.Event_ID
WHERE eventtypes.EventType = 'termination'";
try
{
using (MySqlDataAdapter adapter = new MySqlDataAdapter(cmd, conn))
{
DataSet dataSet = new DataSet();
adapter.Fill(dataSet);
DataTable ds = dataSet.Tables[0];
for (int row = 0; row < ds.Rows.Count; row++)
{
SearchResult result = new SearchResult()
{
EventType = ds.Rows[row]["EventType"].ToString(),
User = ds.Rows[row]["User"].ToString(),
Date = ds.Rows[row]["Date"].ToString(),
PCBID = ds.Rows[row]["PCBID"].ToString(),
EAReason = ds.Rows[row]["EAReason"].ToString().Any() ? ds.Rows[row]["EAReason"].ToString() : null,
ETReason = ds.Rows[row]["ETReason"].ToString().Any() ? ds.Rows[row]["ETReason"].ToString() : null,
Notes = ds.Rows[row]["Notes"].ToString().Any() ? ds.Rows[row]["Notes"].ToString() : null,
Reason = ds.Rows[row]["Reason"].ToString().Any() ? ds.Rows[row]["Reason"].ToString() : null,
SBEJobNumber = ds.Rows[row]["SBEJobNumber"].ToString().Any() ? ds.Rows[row]["SBEJobNumber"].ToString() : null,
SBEModelNumber = ds.Rows[row]["SBEModelNumber"].ToString().Any() ? ds.Rows[row]["SBEModelNumber"].ToString() : null,
SBEPN = ds.Rows[row]["SBEPN"].ToString().Any() ? ds.Rows[row]["SBEPN"].ToString() : null,
SBESerialNumber = ds.Rows[row]["SBESerialNumber"].ToString().Any() ? ds.Rows[row]["SBESerialNumber"].ToString() : null
};
searchResults.Add(result);
}
}
}
catch (MySqlException ex)
{
Console.WriteLine(ex);
}
catch(Exception ex)
{
Console.WriteLine(ex);
}
}
}
catch (MySqlException ex)
{
Console.WriteLine(ex);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
return searchResults;
}
public static XElement TransformSearchResult (SearchResult result)
{
return new XElement("SBE_PCB_Data",
new XAttribute("PCBID", result.PCBID),
new XElement(result.EventType,
new XAttribute("ActionID", result.ActionId),
new XAttribute("User", result.UserAndIP),
new XAttribute("Date", result.Date),
new XAttribute("PCBID", result.PCBID),
result.EAReason == null ? null : new XElement("EAReason", result.EAReason),
result.ETReason == null ? null : new XElement("ETReason", result.ETReason),
result.Reason == null ? null : new XElement("Reason", result.Reason),
result.Notes == null ? null : new XElement("Note", result.Notes),
result.SBEJobNumber == null ? null : new XElement("SBEJobNumber", result.SBEJobNumber),
result.SBEModelNumber == null ? null : new XElement("SBEModelNumber", result.SBEModelNumber),
result.SBEPN == null ? null : new XElement("SBEPN", result.SBEPN),
result.SBESerialNumber == null ? null : new XElement("SBESerialNumber", result.SBESerialNumber)
)
);
}
public static XElement TransformList (IEnumerable<SearchResult> listOfResults)
{
return new XElement("PCBDatabaseReply",
new XElement("SearchResult",
from r in listOfResults
select TransformSearchResult(r)));
}
}
}
이 실행 얻기 위해 일부 조정을 할 수 있었다, 그러나 개념은 소리로 업데이트, 나는 그것을 확장 할 수있는 것을 좋아한다. 아직 정확한 결과물을 제공하지는 못하지만,이를 조정할 수도 있습니다.
팀, 그건 일하고, 감사합니다! 나는 그것을 쉽게 확장 할 수있는 방법을 좋아한다. (내게는 이전에 일주일에 썼던 무차별 대입 방식의 한 세대 만이 확장 성이 전혀 없다.) 내일 당신의 대답을 위해 일할 것이고 질문이 있다면 알려주 겠소.귀하의 가정은 대부분 정확했으며, "EventType"은 변경 될 수 있습니다 (7 가지 가능성 있음).이 중 6 가지가이 테마의 변형으로 이어질 것입니다. 7 번째 버전은 약 5 가지 유형의 테스트 데이터이기 때문에 곰이 될 것입니다. 장치의. 많은 노력에 감사 드리며, 정말로 감사드립니다. – delliottg