【问题标题】:How to decrease xmlattribute id by one after deleting node in c#如何在c#中删除节点后将xmlattribute id减一
【发布时间】:2021-06-15 15:08:50
【问题描述】:

我有一个 c# 控制台应用程序,我必须通过序列化将数据保存到 XML,到目前为止它可以工作,我可以编辑单个节点并删除它们。我的问题是我为每个节点都有一个 id 属性,我用一个技巧使它“独一无二”。每次我将数据保存到我的 XML 时,我都会计算一个列表,然后将 + 1 添加到我的 Id 的当前计数中,它起初工作得很好,但是在删除数据然后添加另一个数据之后,我遇到了两个数据集的问题相同的 ID。在删除数据或仔细检查属性是否具有特定值后,如何使 ids 减 1,然后自动给出不同的 id?

这是我保存数据和 ID 的代码:

public bool saveCustomer()

{
    string filePath = "customerDatabase2.xml";
    serializerHelper sHelper = new serializerHelper();
    List<Kunde> kList = new List<Kunde>();
    var xDoc = XDocument.Load(filePath);

    Console.Clear();
    Console.WriteLine("Bitte geben sie den Namen des Kunden ein!");
    string firstNameInput = Console.ReadLine();
    Console.WriteLine("Bitte geben sie den Nachnamen des Kunden ein!");
    string lastNameInput = Console.ReadLine();
    Console.WriteLine("Bitte geben sie den Adresse des Kunden ein!");
    string adressInput =  Console.ReadLine();
    Console.WriteLine("Bitte geben sie den Geburtsdatum des Kunden ein!");
    string birthdayInput = Console.ReadLine();
    Console.WriteLine("Bitte geben sie den Bankdetails des Kunden ein!");
    string bankDetailsInput = Console.ReadLine();

    kList = sHelper.showData(typeof(List<Kunde>), filePath) as List<Kunde>;

    int id = (from XElement i in xDoc.Root.Descendants("Kunde") select int.Parse(i.Attribute("id").Value)).Max() + 1;


    Kunde customer = new Kunde(id,firstNameInput, lastNameInput, adressInput, birthdayInput, bankDetailsInput,buchung);
    Console.Clear();

        if (File.Exists("customerDatabase2.xml"))
        {
            kList = sHelper.showData(typeof(List<Kunde>), filePath) as List<Kunde>;
            

        }


        kList.Add(customer);

        sHelper.XmlSerialize(typeof(List<Kunde>), kList, filePath);
        Console.WriteLine("Ihr Kunde wurde gespeichert danke für die Zusammenarbeit!");

        Console.Clear();
        Console.WriteLine("Drücken Sie 1 um ins Hauptmenü zu gelangen und auf 2 um die Applikation zu beenden!");
        Program p = new Program();


        switch (Console.ReadLine())
        {
            case "1": Program.menuPoints(); return true;
            case "2": Environment.Exit(0); return true;
           
        }
        return true;
    }

这是我的删除方法:

public void delete()
        {
            string filepath = "customerdatabase2.xml";
            var xDoc = XDocument.Load(filepath);
            Console.WriteLine(xDoc);
            Console.WriteLine("Geben Sie die Id des Kunden an, den Sie löschen möchten!");
            var tgt = xDoc.Root.Descendants("Kunde").FirstOrDefault(x =>
            x.Attribute("id").Value == Console.ReadLine());

            tgt.Remove();
            xDoc.Save(filepath);
        idTester();

            Console.WriteLine("Kunde wurde gelöscht!");
        }

这就是我的 xml 的样子:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfKunde xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Kunde id="2">
    <firstName>sdfc</firstName>
    <lastName>nbv</lastName>
    <adress>bjk</adress>
    <birthday>hjvn</birthday>
    <bankDetails>jhgj</bankDetails>
  </Kunde>
  <Kunde id="3">
    <firstName>mbn,</firstName>
    <lastName>hgj</lastName>
    <adress>ghj</adress>
    <birthday>ghjg</birthday>
    <bankDetails>hghj</bankDetails>
  </Kunde>
  <Kunde id="3">
    <firstName>n</firstName>
    <lastName>lh</lastName>
    <adress>lkj</adress>
    <birthday>lkj</birthday>
    <bankDetails>lj</bankDetails>
  </Kunde>
</ArrayOfKunde>

编辑添加代码:

public void idTester()
        {
            serializerHelper sHelper = new serializerHelper();
            List<Kunde> kList = new List<Kunde>();

            string filepath = "customerdatabase2.xml";
            var xDoc = XDocument.Load(filepath);
            kList = sHelper.showData(typeof(List<Kunde>), filepath) as List<Kunde>;
        int index = 0; 
        List<XElement> Kundes = xDoc.Descendants("Kunde").ToList(); 
        foreach (var Kunde in Kundes) 
        { 
            Kunde.SetAttributeValue("id", ++index); 
        }
        xDoc.Save(filepath);



        }

【问题讨论】:

  • 最好的方法是从一开始重新编号整个列表。
  • 所以你的意思是在删除一个节点后计算列表并再次给他们每个ID?
  • 是的。在列表中间添加数字变得复杂。因此,如果可能,最简单的方法就是对整个列表重新编号。
  • 你能给我一个例子吗?我现在有点卡住了不知道如何开始......我会添加我到目前为止所做的我不知道我是否必须使用 xDoc 或诚实的名单
  • int 索引 = 0; List Kundes = doc.Descendants("Kunde").ToList(); foreach(var Kunde in Kundes) { Kunde.SetAttributeValue("id",++index);}

标签: c# .net xml


【解决方案1】:

您说的是唯一 ID。正确的方法是每个号码只分配一次,而不管删除的条目如何。为此,您需要单独保存您的最后一个 ID。当您添加一个新条目时,它会收到实际 ID,然后您将其加一。

static class XmlEditor
{
    static int id;

    ... // some initialization needed. For example load the current id from a file


    static public bool saveCustomer()
    {
        ...

        Kunde customer = new Kunde(id,firstNameInput, lastNameInput, adressInput, birthdayInput, bankDetailsInput);
        id++;

        ...

    }
}

这样,您将永远不会有两次相同的号码。这也模拟了自动递增主键在数据库中的工作方式。

要获得下一个 ID,您可以搜索 XDocument,选择最高的 ID 并将其加一

int id = (from XElement i in xDoc.Root.Descendants("Kunde") select int.Parse(i.Attribute("id").Value)).Max()+1;

编辑:

我已经对此进行了测试并想出了这个。希望对你有帮助

static void Main(string[] args)
{
    XDocument doc = new XDocument();
    doc.Add(new XElement("Kunden"));
    for(int i =0; i<4; i++)
    {
        AddNewKunde(doc.Root);
    }
    PrintKunden(doc.Root);
    RemoveKunde(doc.Root, 2);
    PrintKunden(doc.Root);

    AddNewKunde(doc.Root);
    PrintKunden(doc.Root);

    Console.ReadLine();
       
}

private static void AddNewKunde(XElement parent)
{
    int id = 0;
    if (parent.Elements().Count() > 0)
    {
        id = (from XElement xe in parent.Elements("Kunde") select int.Parse(xe.Attribute("id").Value)).Max() + 1;
    }

    parent.Add(new XElement("Kunde", new XAttribute("id", id)));
}

private static void RemoveKunde(XElement parent, int id)
{
    parent.Elements("Kunde").Single(x => x.Attribute("id").Value == id.ToString()).Remove();
}

private static void PrintKunden(XElement parent)
{
    foreach (XElement e in parent.Elements())
    {
        Console.WriteLine(e.ToString());
    }
    Console.WriteLine("=====");
}

输出:

<Kunde id="0" />
<Kunde id="1" />
<Kunde id="2" />
<Kunde id="3" />
=====
<Kunde id="0" />
<Kunde id="1" />
<Kunde id="3" />
=====
<Kunde id="0" />
<Kunde id="1" />
<Kunde id="3" />
<Kunde id="4" />
=====

【讨论】:

  • 嗨,您对初始化和从文件加载当前 ID 是什么意思? id的最新条目?
  • 也许我在想。如果您计划在不同时间编辑您的 xml 文件,您需要将 ID 保存在某处。例如在单独的文件或 application.exe.config
  • 不,这只是一个简单的学校项目,目的是展示我们可以使用 c# 不需要 id,即使我只是认为它会为我简化一些事情
  • 为了避免拥有另一个文件,您可以查看所有现有的 Kunde 元素并选择您找到的最高 id。我会相应地修改我的答案
  • 您好,我添加了这一行:int id = (from XElement i in xDoc.Root.Descendants("Kunde") select int.Parse(i.Attribute("id").Value))。最大()+1;它有点工作。但在第二次添加。因此,例如,如果最高 id 为 3,它将首先添加另一个 id 为 3 的 kunde,然后如果我添加另一个 kunde,它将添加一个 4。我将添加我的代码以显示我是如何做到的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多