【问题标题】:Need help reading multiple rows of rows需要帮助读取多行行
【发布时间】:2022-11-13 22:49:13
【问题描述】:

因此,我必须读取 MSSQL 数据库中的所有餐厅记录,并且每个餐厅都有一个表格列表。我的问题在于我知道如何阅读一个餐厅行:

public Restaurant GeefRestaurant(int id)
{
    using (SqlCommand cmd = _connection.CreateCommand())
    {
        try
        {
            _connection.Open();
            string naam;
            string email;
            string telefoonnummer;
            int postcode;
            string gemeente;
            string straat;
            string huisnummer;
            Keuken keuken;
            int tafelnummerOld = -1;
            int tafelnummer = 0;
            int aantalPlaatsen = 0;
            bool isBezet = false;
            bool first = true;
            Locatie l = null;
            Restaurant r = null;
            List<Tafel> tafels = new();
            cmd.CommandText = $"select r.Id RestaurantId, r.naam, r.email, r.telefoonnummer, r.keuken, l.id locatieid, l.postcode, l.gemeente, l.straat, l.huisnummer, t.Tafelnummer, t.aantalplaatsen, t.isbezet " +
                $"from Restaurant r " +
                $"left join locatie l on r.locatieid = l.id " +
                $"left join tafel t on r.id = t.restaurantid " +
                $"where r.id = {id}";
            SqlDataReader reader = cmd.ExecuteReader();
            while (reader.Read())
            {
                if (r == null)
                {
                    postcode = (int)reader["Postcode"];
                    gemeente = (string)reader["Gemeente"];
                    straat = reader["Straat"] == DBNull.Value ? null : (string)reader["Straat"];
                    huisnummer = reader["Huisnummer"] == DBNull.Value ? null : (string)reader["Huisnummer"];
                    keuken = (Enum.Parse<Keuken>((string)reader["keuken"]));
                    naam = (string)reader["naam"];
                    email = (string)reader["Email"];
                    telefoonnummer = (string)reader["telefoonnummer"];

                    l = new(postcode, gemeente, straat, huisnummer);
                    l.ZetId((int)reader["LocatieId"]);

                    r = new(naam, l, telefoonnummer, email, keuken);
                    r.ZetId((int)reader["RestaurantId"]);
                }

                if (!reader.IsDBNull(reader.GetOrdinal("Tafelnummer"))) // heeft tafels
                {
                    tafelnummer = (int)reader["Tafelnummer"];
                    if (tafelnummer != tafelnummerOld)
                    {
                        // Nieuwe tafel of de eerste
                        if (tafelnummerOld > 0)
                        {
                            // Maak tafel, einde bereikt
                            Tafel t = new(tafelnummerOld, aantalPlaatsen, isBezet);
                            r.VoegTafelToe(t);
                        }
                        first = true;
                        tafelnummerOld = tafelnummer;
                    }
                    if (first)
                    {
                        aantalPlaatsen = (int)reader["AantalPlaatsen"];
                        isBezet = (bool)reader["IsBezet"];
                        first = false;
                    }
                }
            }
            reader.Close();
            if (tafelnummer > 0)
            {
                Tafel t = new(tafelnummer, aantalPlaatsen, isBezet);
                r.VoegTafelToe(t);
            }
            return r;
        }
        catch (Exception ex)
        {
            throw new RestaurantRepositoryException("GebruikerRegistreren - repo", ex);
        }
        finally
        {
            _connection.Close();
        }
    }
}

但是我不完全知道如何在代码中读取所有这些,我知道 sql 命令,我尝试了很多东西,但它们都没有做它应该做的事情:/。我想要的是开始读取餐厅行,读出所有表格,然后继续下一个,直到读取所有数据。

我试过这样的东西,但这不起作用......

public IReadOnlyList<Restaurant> GeefAlleRestaurants()
{
    using (SqlCommand cmd = _connection.CreateCommand())
    {
        try
        {
            _connection.Open();
            string naam;
            string email;
            string telefoonnummer;
            int postcode;
            string gemeente;
            string straat;
            string huisnummer;
            Keuken keuken;
            int restaurantIdOld = -1;
            int restaurantId = 0;
            int tafelnummerOld = -1;
            int tafelnummer = 0;
            int aantalPlaatsen = 0;
            bool isBezet = false;
            bool first = true;
            bool firstRestaurant = true;
            Locatie l = null;
            List<Restaurant> restaurants = new();
            //Restaurant r = null;
            List<Tafel> tafels = new();
            cmd.CommandText = $"select r.Id RestaurantId, r.naam, r.email, r.telefoonnummer, r.keuken, l.id locatieid, l.postcode, l.gemeente, l.straat, l.huisnummer, t.Tafelnummer, t.aantalplaatsen, t.isbezet " +
                $"from Restaurant r " +
                $"left join locatie l on r.locatieid = l.id " +
                $"left join tafel t on r.id = t.restaurantid";
            SqlDataReader reader = cmd.ExecuteReader();

            //TODO!
            while (reader.Read())
            {
                if (!reader.IsDBNull(reader.GetOrdinal("RestaurantId"))) // heeft restaurants
                {
                    restaurantId = (int)reader["RestaurantId"];
                    if (restaurantId != restaurantIdOld)
                    {
                        // Nieuwe restaurant of het eerste
                        if (restaurantIdOld > 0)
                        {
                            // Maak restaurant, einde bereikt
                            postcode = (int)reader["Postcode"];
                            gemeente = (string)reader["Gemeente"];
                            straat = reader["Straat"] == DBNull.Value ? null : (string)reader["Straat"];
                            huisnummer = reader["Huisnummer"] == DBNull.Value ? null : (string)reader["Huisnummer"];
                            keuken = (Enum.Parse<Keuken>((string)reader["keuken"]));
                            naam = (string)reader["naam"];
                            email = (string)reader["Email"];
                            telefoonnummer = (string)reader["telefoonnummer"];
                            r = new(naam, l, telefoonnummer, email, keuken);
                            if (reader.HasRows)
                            {
                                if (!reader.IsDBNull(reader.GetOrdinal("Tafelnummer")))
                                {
                                    tafelnummer = (int)reader["Tafelnummer"];
                                    if (tafelnummer != tafelnummerOld)
                                    {
                                        if (tafelnummerOld > 0)
                                        {
                                            Tafel t = new(tafelnummer, aantalPlaatsen, isBezet);
                                            r.VoegTafelToe(t);
                                        }
                                        tafelnummerOld = tafelnummer;
                                        aantalPlaatsen = (int)reader["aantalplaatsen"];
                                        isBezet = (bool)reader["isbezet"];
                                    }
                                }
                            }
                            restaurants.Add(r);
                        }
                        firstRestaurant = true;
                        restaurantIdOld = restaurantId;
                        if (firstRestaurant)
                        {
                            naam = (string)reader["naam"];
                            email = (string)reader["Email"];
                            telefoonnummer = (string)reader["telefoonnummer"];
                            postcode = (int)reader["Postcode"];
                            gemeente = (string)reader["Gemeente"];
                            straat = reader["Straat"] == DBNull.Value ? null : (string)reader["Straat"];
                            huisnummer = reader["Huisnummer"] == DBNull.Value ? null : (string)reader["Huisnummer"];
                            keuken = (Enum.Parse<Keuken>((string)reader["keuken"]));

                            l = new(postcode, gemeente, straat, huisnummer);
                            l.ZetId((int)reader["LocatieId"]);

                            r = new(naam, l, telefoonnummer, email, keuken);
                            r.ZetId((int)reader["RestaurantId"]);
                            if (reader.HasRows)
                            {
                                if (!reader.IsDBNull(reader.GetOrdinal("Tafelnummer")))
                                {
                                    tafelnummer = (int)reader["Tafelnummer"];
                                    if (tafelnummer != tafelnummerOld)
                                    {
                                        if (tafelnummerOld > 0)
                                        {
                                            Tafel t = new(tafelnummer, aantalPlaatsen, isBezet);
                                            r.VoegTafelToe(t);
                                        }
                                        tafelnummerOld = tafelnummer;
                                        aantalPlaatsen = (int)reader["aantalplaatsen"];
                                        isBezet = (bool)reader["isbezet"];
                                    }
                                }
                            }
                            restaurants.Add(r);
                        }
                    }
                }
            }
            reader.Close();
            return restaurants;
        }
        catch (Exception ex)
        {
            throw new RestaurantRepositoryException("GebruikerRegistreren - repo", ex);
        }
        finally
        {
            _connection.Close();
        }
    }
}

我还尝试创建另一种返回列表的方法,以便我可以使用此方法而不是尝试从数据库中获取所有 Tafel 记录,但我收到一个错误,表明连接已打开,我不知道这是否好实践...

【问题讨论】:

  • 我会指出您阅读有关 ORM 的内容并在您的上下文中使用这些库。有一个很好的没有很多包袱的叫Dapper。然而,这需要你付出一些努力,因为有一些东西需要学习,尽管从长远来看它会回报你
  • 小心,该查询看起来很容易受到注入攻击;一个严重的致命安全漏洞。

标签: c# sql-server ado.net


【解决方案1】:

如果您没有明确指定一个 SQL 查询,则不能保证以任何特定顺序返回记录。由于您想在餐厅 id 更改时将新餐厅添加到列表中,因此您必须按餐厅 id 订购

SELECT r.Id RestaurantId, r.naam, r.email, ...
FROM Restaurant r
LEFT JOIN locatie l ON r.locatieid = l.id
LEFT JOIN tafel t ON r.id = t.restaurantid
ORDER BY r.id

注意,因为餐厅 id 是主键,所以不能为空。因此,不要针对 DbNull 对其进行测试。但是位置和表是左连接的,因此可以为空,例如如果餐厅没有定义位置或桌子。

每个餐厅的表应该只出现一次,因此 Tafelnummer 必须是主键或具有唯一索引。

位置可以按任何顺序出现,并且可以分配给多个餐厅。因此,我建议将它们添加到以表号为键的字典中。这使我们能够轻松地查找。

那么逻辑就变成了

List<Restaurant> restaurants = new();
List<Tafel> tafels = new();
Dictionary<int, Locatie> locations = new();
int restaurantIdOld = -1;
... (skipping details)
while (reader.Read()) {
    int restaurantId = (int)reader["RestaurantId"];
    if (restaurantId != restaurantIdOld) {
        Locatie l = null;
        if (reader["LocatieId"] is int locId &&
           !locations.TryGetValue(locId, out l))
        {
            //TODO: get location fields
            l = new(postcode, gemeente, straat, huisnummer);
            locations.Add(locId, l);
        }

        //TODO: get restaurant fields
        r = new(naam, l, telefoonnummer, email, keuken);
        restaurants.Add(r);
    }
    //TODO: get table fields
    // No need to test whether this is a new table. Tables are unique.
    Tafel t = new(tafelnummerOld, aantalPlaatsen, isBezet);
    tafels.Add(t);
    r.VoegTafelToe(t);
}

我们还可以从 SQL 字符串中删除 $ 因为我们没有任何字符串插值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-10
    • 2013-06-17
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 2019-11-14
    相关资源
    最近更新 更多