Получить результат родительского / дочернего запроса SQL Server с помощью c # - PullRequest
2 голосов
/ 23 августа 2011

То, что я делаю здесь сейчас, это, вероятно, худший способ выполнения моих требований, но я не нашел другого пути.

вот мой пример структуры базы данных;

enter image description here

Вот скрипт, который я использую для получения определенных значений;

SELECT DISTINCT h.HotelID, h.HotelName, r.RoomCode, r.RoomName, r.RoomID 
FROM RoomsInHotel rh 
INNER JOIN Hotels h ON rh.HotelID = h.HotelID 
INNER JOIN  Rooms r ON rh.RoomID = r.RoomID 
order by h.HotelName, r.RoomCode;

Вот результат, который приведенный выше скрипт возвращает мне;

enter image description here

пока все хорошо.

Мне нужно перейти на C # код отсюда. Я хотел бы добиться следующего результата:

enter image description here

Вот где я волнуюсь. Я использую Linq для достижения этой цели, и приведенный ниже код является кодом, который я использовал для приведенного выше результата консоли.

    public class Hotel { 
      public int HotelID {get; set; }
      public string HotelName {get; set; }
      public IQueryable<Room> Rooms {get; set; }
    }

    public class HotelWithOneRoom {
        public int HotelID { get; set; }
        public string HotelName { get; set; }
        public Room Room { get; set; }
    }

    public class Room { 
      public int RoomID {get; set; }
      public string RoomCode {get; set; }
      public string RoomName { get; set; }
    }

    class Program {

        static void Main(string[] args) {

            #region _assets

            IList<HotelWithOneRoom> tempHotelWithOneRoom = new List<HotelWithOneRoom>();
            IList<Hotel> tempDistinctHotels = new List<Hotel>();
            IList<Room> tempRooms = new List<Room>();

            #endregion

            #region _connectionString

            var connectionString = "Data Source=TOSHIBA-PC\\SQLEXPRESS;Initial Catalog=tbAccomm;Integrated Security=True";

            #endregion

            using (SqlConnection conn = new SqlConnection(connectionString)) {

                using(SqlCommand cmd = conn.CreateCommand()) {

                    #region _connect to db, generate script and retrieve values

                    cmd.CommandText = "SELECT DISTINCT h.HotelID, h.HotelName, r.RoomCode, r.RoomName, r.RoomID FROM RoomsInHotel rh INNER JOIN Hotels h ON rh.HotelID = h.HotelID INNER JOIN Rooms r ON rh.RoomID = r.RoomID order by h.HotelName, r.RoomCode;";
                    cmd.CommandType = System.Data.CommandType.Text;

                    conn.Open();
                    SqlDataReader r = cmd.ExecuteReader();

                    #endregion

                    #region _assigning the values to tempHotelWithOneRoom

                    while (r.Read()) {

                        tempHotelWithOneRoom.Add(new HotelWithOneRoom {
                            HotelID = int.Parse(r["HotelID"].ToString()),
                            HotelName = r["HotelName"].ToString(),
                            Room = new Room {
                                RoomID = int.Parse(r["RoomID"].ToString()),
                                RoomCode = r["RoomCode"].ToString(),
                                RoomName = r["RoomName"].ToString()
                            }
                        });
                    }

                    #endregion

                    foreach (var item in tempHotelWithOneRoom) {

                        if (tempDistinctHotels.Where(x => x.HotelID == item.HotelID).Count() < 1) {

                            tempDistinctHotels.Add(new Hotel { 
                                HotelID = item.HotelID,
                                HotelName = item.HotelName
                            });

                            var _tempHotel = tempDistinctHotels.Single(x => x.HotelID == item.HotelID);
                            var _tempRoomList = new List<Room>();

                            if (_tempHotel.Rooms != null) { 
                                foreach (var _item in _tempHotel.Rooms) {
                                    _tempRoomList.Add(_item);
                                }
                            }

                            _tempRoomList.Add( new Room { 
                                RoomCode = item.Room.RoomCode,
                                RoomID = item.Room.RoomID,
                                RoomName = item.Room.RoomName
                            });

                            _tempHotel.Rooms = _tempRoomList.AsQueryable();

                        } else {

                            var _tempHotel = tempDistinctHotels.Single(x => x.HotelID == item.HotelID);
                            var _tempRoomList = new List<Room>();

                            if (_tempHotel.Rooms != null) { 
                                foreach (var _item in _tempHotel.Rooms) {
                                    _tempRoomList.Add(_item);
                                }
                            }

                            _tempRoomList.Add( new Room { 
                                RoomCode = item.Room.RoomCode,
                                RoomID = item.Room.RoomID,
                                RoomName = item.Room.RoomName
                            });

                            _tempHotel.Rooms = _tempRoomList.AsQueryable();
                        }
                    }

                    #region _output the result

                    foreach (var item in tempDistinctHotels) {

                        Console.WriteLine(
                            "Hotel Name : " + item.HotelName + ", " +  "Room Count : " + item.Rooms.Count()
                            );

                        foreach (var item2 in item.Rooms) {
                            Console.WriteLine("--" + item2.RoomCode + ", " + item2.RoomName);
                        }
                    }

                    #endregion

                    r.Close();
                    Console.Read();
                }

            }

        }
    }

IMO, если бы был конкурс на худший код c #, я бы выиграл этот конкурс с этим кодом. (не так ли?)

Итак, как лучше всего делать то, что я делаю?

Ответы [ 4 ]

3 голосов
/ 23 августа 2011

C # не мой язык выбора, но вы идете:

Dictionary<int, Hotel> Hotels = new Dictionary<int, Hotel> ();
while (r.Read()) {
    if (!Hotels.ContainsKey(r["HotelID"])) {
        NewHotel Hotel= new Hotel();
        NewHotel.HotelID = r["HotelID"];
        Newhotel.HotelName = r["HotelName"];
        NewHotel.Rooms = new Dictionary<int, Room> ();
        Hotels.Add(NewHotel);
    }
    Room NewRoom = new Room();
    NewRoom.RoomID = r["RoomName"];
    NewRoom.RoomCode = r["RoomCode"];
    NewRoom.RoomName = r["RoomName"];
    Hotels.Items("HotelID").Rooms.Add(NewRoom);
}

Как указал jpmcclung, для создания успешных Приложений вам понадобятся навыки разработки программного обеспечения. Чем больше ваш проект, тем больше дизайна и планирования требуется.

1 голос
/ 23 августа 2011

Поскольку вы включили IQueryable в свой пример, можем ли мы предположить, что LINQ to SQL или EF - это вариант для вашего решения?Если это так, поймите, что они поддерживают проецирование в объектные иерархии напрямую.

При условии, что между таблицами установлены ассоциации, это может быть так просто:

var query = from hotel in context.hotels
             select new Hotel { HotelID = hotel.HotelID,
                                HotelName = hotel.HotelName,
                                Rooms = (from room in hotel.Rooms
                                        select new Room { 
                                            RoomID = room.RoomID,
                                            RoomCode = room.RoomCode, 
                                            RoomName = room.RoomName })
                                        .Distinct()
             }; 
1 голос
/ 23 августа 2011

Лучший способ обойти такое написание кода - это изучить практику тестового проектирования. Этот код кричит об этом. Чтобы увидеть его в действии, я бы посмотрел новое видео Брэда Уилсона с полным дросселем TDD на TekPub (http://shop.tekpub.com/products/ft_tdd_wilson) это 12 баксов, но оно того стоит. В противном случае есть множество ресурсов на эту тему.

В частности, зачем вам HotelWithOneRoom? Просто добавьте одну комнату к списку номеров в обычном отеле. Почему бы вам не переопределить .ToString () в отеле и использовать StringBuilder для создания строки вывода для отеля? Это всего лишь несколько вещей, которые мне не нравятся, но если вы используете TDD, это поможет организовать вашу практику проектирования и избавит вас от этого кода.

0 голосов
/ 01 сентября 2011

Я думаю, вы могли бы начать с самого начала и избежать путаницы, переименовав свои таблицы. Я думаю, что ваши имена таблиц должны быть Hotel, Room и RoomType (я не фанат множественных имен таблиц, но это не относится к делу).

Чтобы мыслить терминами «Домен», у вас есть гостиница. В отеле есть номера. Каждая комната определяется как тип комнаты: двухместный, одноместный и т. Д. ...

Во всяком случае, я собрал код, который делает то же самое, что и ваш. Это немного яснее, я думаю. Для доступа к базе данных я использовал Massive https://github.com/robconery/massive, потому что это быстро и весело.

В любом случае, вот код, который я придумал.

    class Program {
        static void Main(string[] args) {
            const string sqlStmnt = @"SELECT h.HotelID, h.HotelName, r.HotelRoomID, rt.RoomTypeCode, rt.RoomTypeName FROM Hotel h INNER JOIN HotelRoom r ON r.HotelID = h.HotelID INNER JOIN  RoomType rt ON r.RoomTypeID = rt.RoomTypeID order by h.HotelName, rt.RoomTypeCode";
            var context = new HotelContext();
            var hotelData =  context.Query(sqlStmnt);
            var hotelList = new List<Hotel>();

            //Load our objects
            foreach (dynamic data in hotelData) {
                int hotelID = data.HotelID;
                var hotel = hotelList.Where(h => h.HotelID == hotelID).FirstOrDefault()
                                      ?? new Hotel() {HotelName = data.HotelName};
                hotel.AddRoom(new HotelRoom { HotelRoomID = data.HotelRoomID, RoomType = new RoomType{ TypeCode = data.RoomTypeCode, TypeDescription = data.RoomTypeName}});

                if (hotel.HotelID != 0) {continue;}
                hotel.HotelID = hotelID;
                hotelList.Add(hotel);
            }

            //Display our output
            foreach (var hotel in hotelList) {
                Console.WriteLine("Hotel Name : " + hotel.HotelName + ", Room Count : " + hotel.HotelRooms.Count());
                foreach (var room in hotel.HotelRooms) {
                    Console.WriteLine("--" + room.RoomType.TypeCode + ", " + room.RoomType.TypeDescription);
                }
            }

            Console.ReadLine();
         }
    }

Вот моя база данных.

    public class HotelContext : DynamicModel {
        public HotelContext():base("test") {
        PrimaryKeyField = "HotelID";
        TableName = "Hotel";
        }
    }

Вот классы, которые я использовал. Не мог понять, для чего предназначен ваш HotelWithOneRoom.

    public class Hotel{
        private readonly List<HotelRoom> _rooms = new List<HotelRoom>();
        public int HotelID { get; set; }
        public string HotelName { get; set; }
        public void AddRoom(HotelRoom room) {_rooms.Add(room);}
        public IQueryable<HotelRoom> HotelRooms {get {return _rooms.AsQueryable();}}
    }
    public class HotelRoom {
        public int HotelRoomID { get; set; }
        public RoomType RoomType { get; set; }
    }

    public class RoomType {
        public string TypeCode { get; set; }
        public string TypeDescription { get; set; }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...