C# 当从控制台应用程序传递值时,如何覆盖数据库中的行?
我目前正在开发一个工具,它可以从目录中提取一些XML文件,然后将值传递给数据库。每次我运行代码时,这些值都会堆积在数据库中,并出现重复项。这些文件可能会更改,因此代码将偶尔运行以保持数据库更新,因此我需要拿出一个代码来完成以下条件:C# 当从控制台应用程序传递值时,如何覆盖数据库中的行?,c#,sql-server,xml,linq,console-application,C#,Sql Server,Xml,Linq,Console Application,我目前正在开发一个工具,它可以从目录中提取一些XML文件,然后将值传递给数据库。每次我运行代码时,这些值都会堆积在数据库中,并出现重复项。这些文件可能会更改,因此代码将偶尔运行以保持数据库更新,因此我需要拿出一个代码来完成以下条件: 如果从XML文件中刮取的值与数据库中的值不同,请添加新行 如果从XML文件中刮取的值与从数据库中刮取的值相同,请覆盖从数据库中刮取的值 如果数据库中的值未被覆盖,请将其标记为过期。(将值1或0放在名为“已标记”的列中) 现在我已经对我认为需要做的事情做了一个简短的总
foreach (var file in new DirectoryInfo(@"C:\GS1").GetFiles().OrderByDescending(f => f.LastWriteTimeUtc))
{
try
{
var xDocument = XDocument.Load(file.FullName);
foreach (XElement XE in xDocument.Descendants())
{
XE.Name = XE.Name.LocalName;
XE.ReplaceAttributes((from xattrib in XE.Attributes().Where(xa => !xa.IsNamespaceDeclaration) select new XAttribute(xattrib.Name.LocalName, xattrib.Value)));
}
var tradeItems = xDocument.Descendants().Where(f => f.Name == "tradeItem");
foreach (var tradeItem in tradeItems)
{
if (tradeItem.Elements().Any(f => f.Name == "isTradeItemAConsumerUnit" && bool.Parse(f.Value)))
{
...
var gtin = tradeItem.Elements().FirstOrDefault(f => f.Name == "gtin")?.Value?.Trim();
var ingredients = tradeItem.Descendants().FirstOrDefault(f => f.Name == "ingredientStatement")?.Value?.Trim();
var tradeMarket = tradeItem.Descendants().FirstOrDefault(f => f.Name == "tradeItemMarketingMessage")?.Value?.Trim();
因此,上面的代码描述了我实际上是如何获取这些值的,这些值是我以后要传递给数据库的。省略了一些代码,但我只想包含最相关的内容
然后调用Save()
方法,方法如下:
private static void Save(FileInfo file, string gtin, string brandName, string partyName, string descriptionShort, string functionalName, string netContent, string fileName, string extension, byte[] image, string angle, DateTime? qualificationDate, string ingredients, DataTable nutritionFacts, string tradeMarket, string imageLink)
{
for(int i=0;i<3;i++)
{
try
{
using (SqlConnection conn = new SqlConnection("Server = xxxxxxxxx; Initial Catalog = dinkurv_dev; Persist Security Info = False; User ID = radu; Password =xxxxx;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"))
{
...
conn.Execute("INSERT INTO GS1MarketingInformation VALUES (@gtin, @tradeMarket)", new { gtin, tradeMarket });
conn.Execute("IF EXISTS(SELECT * from GS1IngredientInformation WHERE GTIN=@gtin) UPDATE GS1IngredientInformation SET GTIN=@gtin, @Ingredient_Information=@ingredients" +
"ELSE INSERT INTO GS1IngredientInformation VALUES (@gtin, @tradeMarket)", new { gtin, ingredients });
break;
}
}
catch (Exception exc)
{
}
}
}
这是一种覆盖数据库中已有内容的尝试,如果数据库中不存在新值,则添加新值。然而,第二个代码并不能真正正常工作。据我所见,它只是删除每一行,然后用另一组值替换它
总结:我如何重新编写上面的代码,使其符合我提到的3个条件?我觉得我很接近实现覆盖,但我有限的SQL知识有点拖我后腿 我看到的第一件事是update语句正在更新表中的每一行。您可能需要放入where子句,以便只更新要更新的行。例如,UPDATE Table SET Row1='fake value',其中id=1将仅更新数据库表中id列中值为1的行。我强烈建议您更改数据库的凭据。在公共网站上共享凭据基本上意味着数据不再是你的;只要有正确的权限,任何人都可以更改数据。除此之外,您应该仔细查看MERGE语句,它允许您在一条语句中进行插入和更新。@Caramiriel woah,我遗漏了那段代码。谢谢你把它编辑出来。另外,谢谢你们的其他意见,我会仔细研究你们的答案,看看我能不能把它整理出来。
conn.Execute("IF EXISTS(SELECT * from GS1IngredientInformation WHERE GTIN=@gtin) UPDATE GS1IngredientInformation SET GTIN=@gtin, @Ingredient_Information=@ingredients" +
"ELSE INSERT INTO GS1IngredientInformation VALUES (@gtin, @tradeMarket)", new { gtin, ingredients });